내 컨트롤러 방법은 다음과 같습니다.
[HttpPost]
[Authorize]
[Route(RouteConfig.Routes.LovList.contactStatus)]
public IHttpActionResult ContactStatusList()
{
try
{
var result = new DBClass.HeroDb().GetList(
DBClass.DBConstants.ListConstants.query_Contact_Status);
return Json(new Models.Response(
Models.ResponseMessages.Success,
result)
);
}
catch(System.Data.SqlClient.SqlException)
{
return InternalServerError();
}
catch(System.Exception ex)
{
Logger.Error(ex, ex.Message, ex.StackTrace);
return InternalServerError();
}
}
그리고 이것은 내 테스트 케이스 방법입니다.
[TestMethod()]
public void ContactStatusListTest()
{
Mock<DBClass.HeroDb> mock = new Mock<DBClass.HeroDb>();
mock.Setup(x => x.GetList(DBClass.DBConstants.ListConstants.query_Contact_Status))
.Returns(CreateContactList());
var result = new ListController().ContactStatusList();
Models.Response response = (Models.Response)result;
Assert.AreEqual(response.Message, Models.ResponseMessages.Success);
Assert.IsNotNull(response.Data);
}
public System.Data.DataTable CreateContactList()
{
DataTable table = new DataTable();
table.Columns.Add("ContactStatus");
DataRow row1 = table.NewRow();row1["ContactStatus"] = "Contacted"; table.Rows.Add(row1);
DataRow row2 = table.NewRow(); row2["ContactStatus"] = "Not Contacted"; table.Rows.Add(row2);
DataRow row3 = table.NewRow(); row3["ContactStatus"] = "Contacted"; table.Rows.Add(row3);
return table;
}
내 테스트 메서드에서 GetList () 함수 를 조롱하려고했지만 작동하지 않습니다. 컨트롤러 메서드에서 내부 서버 오류가 발생합니다. Conrol은
var result = new DBClass.HeroDb()
.GetList(DBClass.DBConstants.ListConstants.query_Contact_Status);
이 줄과 db 개체는 여기서 null입니다. 나는 단위 테스트 케이스 구축의 초보자이므로 도와주세요.
우선 기초를 먼저 설정해 보겠습니다. 단위 테스트는 통합 테스트와 다릅니다 .
이 경우 컨트롤러의 메서드에 대한 단위 테스트입니다ContactStatusList
. 이 방법 만 테스트하고 있으며 실제로 HeroDb
개체 를 조롱하여 작업을 올바르게 수행했습니다 . 이 개체 는 종속성 이므로 모의로 결정했습니다 .
문제는 당신이 모의을 설정하지만에 있기 때문에 당신이 그것을 사용하지 않는 것입니다 ContactStatusList
방법은 전화 new DBClass.HeroDb()
.
두 번째 문제는 수업을 모의하려고한다는 것입니다. 이것은 실제로 가능하지만 모의하려는 모든 클래스의 메서드는 가상으로 선언되어야합니다. 따라서 실제로 인터페이스를 조롱하는 것이 좋습니다.
이 인터페이스는 ListController
. 웹 프로젝트를 정기적으로 실행할 때 시작시 해당 인터페이스의 인스턴스를 삽입하지만 단위 테스트에서는 ListController
의 생성자에 모의를 제공합니다 .
이 규칙을 기억하십시오. 모든 종속성은 컨트롤러의 생성자에 의해 수신되어야합니다.
다음은 인터페이스와 DbHero 클래스입니다.
public interface IDbHero
{
IEnumerable<Contact> GetList(QueryContactStatus status);
}
public class DbHero : IDbHero
{
public IEnumerable<Contact> GetList(QueryContactStatus status)
{
// Implementation here
}
}
이제 컨트롤러가 있습니다.
[ApiController]
[Route("api/[controller]")]
public class ListController: ControllerBase
{
private readonly IHeroDb _heroDb;
public ListController(IHeroDb heroDb)
{
_heroDb = heroDb ?? throw new ArgumentNullException(nameof(heroDb));
}
[HttpPost]
[Authorize]
[Route(RouteConfig.Routes.LovList.contactStatus)]
public IHttpActionResult ContactStatusList()
{
try
{
var result = _heroDb.GetList(DBClass.DBConstants.ListConstants.query_Contact_Status);
return Json(new Models.Response(
Models.ResponseMessages.Success,
result)
);
}
catch(System.Exception ex)
{
Logger.Error(ex, ex.Message, ex.StackTrace);
throw;
}
}
}
SqlException
처리되지 않은 예외가있는 경우 서버가 내부 서버 오류를 반환하므로 오류를 기록하지 않으면 잡는 것이 쓸모가 없기 때문에 어쨌든 잡는 블록 만 제거 했습니다. 또한 두 번째 catch 블록 throw
에서 서버가 자동으로 내부 서버 오류를 반환합니다. 디버그 모드에있는 경우 전체 예외가 반환되므로 유용 할 수 있지만 반환 InternalServerError()
하면 디버그에서도 정보를 얻지 못하며 로그를 확인해야합니다.
클래스 의 ConfigureServices
메소드 Startup.cs
에서 IDbHero
인터페이스 구현을 삽입하십시오 . 이는 범위 가 지정된 서비스이므로 각 HTTP 요청에 대해 새 인스턴스가 생성됩니다. 개인적으로 데이터베이스 액세스 레이어를 싱글 톤 으로 삽입하지 않습니다 .이 레이어가 구현되는 방식에 따라 몇 가지 문제가 발생할 수 있기 때문입니다. 예를 들어 EF Core의 DbContext 는 싱글 톤 패턴 과 호환되지 않습니다 .
services.AddScoped<IDbHero>(_ => new DBClass.HeroDb(Configuration.GetConnectionString("DbHeroConnectionString")));
코드 예제에 연결 문자열에 대한 언급이 없기 때문에 데이터베이스와의 연결을 어떻게 처리하는지 모르겠지만 위와 같은 작업을 수행합니다.
연결 문자열은 appsettings.json
구성 파일 에서 가져옵니다.
"ConnectionStrings": {
"DbHeroConnectionString": "YourConnectionString"
}
이제 단위 테스트에서 모의 객체를 사용하려면 다음과 같이하십시오.
[TestMethod()]
public void ContactStatusList_ShouldReturnData_WhenCalled()
{
// ARRANGE
var mock = new Mock<IHeroDb>();
mock.Setup(x => x.GetList(DBClass.DBConstants.ListConstants.query_Contact_Status))
.Returns(CreateContactList());
var sut = new ListController(mock.Object);
// ACT
var result = sut.ContactStatusList();
// ASSERT
Models.Response response = (Models.Response)result;
Assert.AreEqual(response.Message, Models.ResponseMessages.Success);
Assert.IsNotNull(response.Data);
}
여기에서 몇 가지 사항에 주목하십시오.
단위 테스트 이름 : 다음 3 가지가 표시되어야합니다.
매개 변수에 잘못된 값이있을 때 메서드가 오류를 반환하는지 예를 들어 테스트 할 수 있습니다. 다른 단위 테스트에서 테스트해야합니다.
단위 테스트는 3 개 부분으로 항상 ARRANGE
, ACT
하고 ASSERT
. 코드를 더 잘 구성 할 수 있도록 각 테스트에서 작성하는 것이 항상 좋은 방법입니다.
sut
의미 System Under Test
: 이것은 당신이 테스트하고 싶은 DbHero
것이고 , 다른 모든 의존성 (당신의 레이어 와 같은 )은 모의 되어야합니다.
이제 다음 단계는 단위 테스트를 작성하여 DbHero.GetList
. 이번에 DbHero
는 테스트하려는 것이기 때문에 클래스 의 실제 인스턴스 (모의가 아님)를 만들 것입니다 . 이것이 바로 sut 입니다.
저는 테스트에서 중급 수준이므로 제가 보여 드리는 것은 동료들로부터 배운 모범 사례입니다. 그러나 더 많은 경험 개발자가 저보다 더 나은 방법을 제시 할 수 있습니다.
이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.
침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제
몇 마디 만하겠습니다