AutoFixture를 사용하여 종속성 모의
-
21-12-2019 - |
문제
최근 AutoFixture+AutoMoq을 사용하기 시작했고 다음 인스턴스를 생성하려고 합니다. Func<IDbConnection>
(즉, 연결 팩토리)
var fixture = new Fixture().Customize(new AutoMoqCustomization());
var connectionFactory = fixture.Create<Func<IDbConnection>>();
이것은 꽤 잘 작동하는 것 같습니다:
- 테스트 중인 내 시스템은 대리자를 호출할 수 있으며 이는 모의 객체를 얻습니다.
IDbConnection
- 그런 다음 전화를 걸 수 있습니다.
CreateCommand
, 그러면 나에게 조롱거리가 될 것입니다IDbCommand
- 그런 다음 전화를 걸 수 있습니다.
ExecuteReader
, 그러면 나에게 조롱거리가 될 것입니다IDataReader
이제 모의 객체에 대해 추가 설정을 수행하고 싶습니다. IDataReader
, 예를 들어 반환하도록 설정 true
언제 Read()
호출됩니다.
내가 읽은 것에서 나는 사용해야합니다 Freeze
이를 위해:
var dataReaderMock = fixture.Freeze<Mock<IDataReader>>();
dataReaderMock.Setup(dr => dr.Read())
.Returns(true);
그래도 이건 내 기대에 미치지 못하는 것 같다.내가 전화할 때 IDbCommand.ExecuteReader
, 방금 동결/설정한 리더와 다른 리더를 얻게 됩니다.
예는 다음과 같습니다.
var fixture = new Fixture().Customize(new AutoMoqCustomization());
var dataReaderMock = fixture.Freeze<Mock<IDataReader>>();
dataReaderMock.Setup(dr => dr.Read())
.Returns(true);
//true - Create<IDataReader> retrieves the data reader I just mocked
Assert.AreSame(dataReaderMock.Object, fixture.Create<IDataReader>());
//false - IDbCommand returns a different instance of IDataReader
Assert.AreSame(dataReaderMock.Object, fixture.Create<IDbCommand>().ExecuteReader());
내가 도대체 뭘 잘못하고있는 겁니까?다음과 같은 다른 설비를 어떻게 구하나요? IDbCommand
, 조롱된 인스턴스를 사용하려면 IDataReader
?
해결책
3.20.0부터 다음을 사용할 수 있습니다. AutoConfiguredMoqCustomization
.그러면 멤버의 반환 값이 AutoFixture에 의해 생성되도록 모든 모의 객체가 자동으로 구성됩니다.
예: IDbConnetion.CreateCommand
반환하도록 자동으로 구성됩니다. IDbCommand
고정 장치에서 IDbCommand.ExecuteReader
반환하도록 자동으로 구성됩니다. IDataReader
고정 장치에서.
이제 모든 테스트를 통과해야 합니다.
var fixture = new Fixture().Customize(new AutoConfiguredMoqCustomization());
var dataReaderMock = fixture.Freeze<Mock<IDataReader>>();
dataReaderMock.Setup(dr => dr.Read())
.Returns(true);
//all pass
Assert.Same(dataReaderMock.Object, fixture.Create<IDataReader>());
Assert.Same(dataReaderMock.Object, fixture.Create<IDbCommand>().ExecuteReader());
Assert.Same(dataReaderMock.Object, fixture.Create<IDbConnection>().CreateCommand().ExecuteReader());
Assert.Same(dataReaderMock.Object, fixture.Create<Func<IDbConnection>>()().CreateCommand().ExecuteReader());
다른 팁
당신은해야 Freeze
그만큼 Mock<IDbCommand>
또한 – 기존 객체를 반환하도록 모의 객체를 (스텁으로) 설정합니다. dataReaderMock.Object
사례.
테스트의 정렬 단계에 다음을 추가하면 테스트가 통과됩니다.
var dbCommandStub =
fixture
.Freeze<Mock<IDbCommand>>()
.Setup(x => x.ExecuteReader())
.Returns(dataReaderMock.Object);
Nikos의 해결책이 작동하는 동안 나는 조롱을 권장하지 않을 것입니다.
내 의견에서 테스트가 이해하기가 어렵고 유지 보수가 어려울 것이며, 테스트가 당신에게 주어야 할 확신을주지 않을 것입니다.
데이터베이스가 느려지지만 데이터 레이어를 테스트하여 데이터 계층을 테스트하는 것이 좋습니다.
조롱을위한 모범 사례와 관련 하여이 기사를 읽는 것이 좋습니다. http://codebetter.com/JEREMYMILLER / 2006 / 01 / 10 / BEST-and-and-~ 최악의 관행 - 모의 - 개체 /
다른 사람들을 조롱하지 마십시오 : http:///aspiringcantman.com/2012/04/01 / TDD-Best-Practices-mok-mock /
나는 당신의 정확한 상황을 모르지만 어쨌든 나는 이것을 공유하고 싶었다.