나중에 메서드를 호출했는지 확인하면 콜백에 어설 션을 수행 할 수 있습니까? 이것은 내 모의 모형이 예상 된 매개 변수를 전달하도록하는 선호 된 방법인가요? 아니면 콜백에 지역 변수를 설정하고 해당 인스턴스에 대한 주장을해야합니까?Mock으로 전달되는 매개 변수를 확인하는 올바른 방법은 예상대로 설정됩니다.
필자는 입력을 기반으로 값을 유도하고 Creator 클래스에 전달하는 Presenter 클래스에 일부 논리가있는 상황이 있습니다. Presenter 클래스의 논리를 테스트하려면 Creator가 호출 될 때 적절한 파생 값이 관찰되는지 확인해야합니다. 그 작동 아래의 예를 함께했다,하지만 난이 방법 좋아 있는지 확실하지 않습니다 :
[TestFixture]
public class WidgetCreatorPresenterTester
{
[Test]
public void Properly_Generates_DerivedName()
{
var widgetCreator = new Mock<IWidgetCreator>();
widgetCreator.Setup(a => a.Create(It.IsAny<Widget>()))
.Callback((Widget widget) =>
Assert.AreEqual("Derived.Name", widget.DerivedName));
var presenter = new WidgetCreatorPresenter(widgetCreator.Object);
presenter.Save("Name");
widgetCreator.Verify(a => a.Create(It.IsAny<Widget>()), Times.Once());
}
}
나는 때문에 마지막에 Verify
호출하지 않고 걱정, 보장은 없습니다를 그 어설에서 콜백이 호출됩니다. 또 다른 방법은 콜백에서 로컬 변수를 설정하는 것입니다 :
[Test]
public void Properly_Generates_DerivedName()
{
var widgetCreator = new Mock<IWidgetCreator>();
Widget localWidget = null;
widgetCreator.Setup(a => a.Create(It.IsAny<Widget>()))
.Callback((Widget widget) => localWidget = widget);
var presenter = new WidgetCreatorPresenter(widgetCreator.Object);
presenter.Save("Name");
widgetCreator.Verify(a => a.Create(It.IsAny<Widget>()), Times.Once());
Assert.IsNotNull(localWidget);
Assert.AreEqual("Derived.Name", localWidget.DerivedName);
}
나는 더 명시 때문에이 방법을 적은 오류가 발생하기 쉬운이라고 생각하고는 Assert
문이 호출되는 것을 볼 쉽다. 한 접근법이 다른 접근보다 바람직합니까? 누락 된 모의 객체에 전달 된 입력 매개 변수를 테스트하는 간단한 방법이 있습니까?
public class Widget
{
public string Name { get; set; }
public string DerivedName { get; set; }
}
public class WidgetCreatorPresenter
{
private readonly IWidgetCreator _creator;
public WidgetCreatorPresenter(IWidgetCreator creator)
{
_creator = creator;
}
public void Save(string name)
{
_creator.Create(
new Widget { Name = name, DerivedName = GetDerivedName(name) });
}
//This is the method I want to test
private static string GetDerivedName(string name)
{
return string.Format("Derived.{0}", name);
}
}
public interface IWidgetCreator
{
void Create(Widget widget);
}
편집 내가 사용하기 쉽게 질문에 설명 된 두 번째 방법을 할 수있는 코드를 업데이트
: 그것은 도움이 될 것입니다 경우
, 여기에이 예제 코드의 나머지 부분입니다 . Setup/Verify에서 사용 된 표현식을 별도의 변수로 생성하여 한 번만 정의하면됩니다. 나는이 방법이 내가 가장 편안하다고 느낀다. 설치하기 쉽고 좋은 오류 메시지로 실패한다.
[Test]
public void Properly_Generates_DerivedName()
{
var widgetCreator = new Mock<IWidgetCreator>();
Widget localWidget = null;
Expression<Action<IWidgetCreator>> expressionCreate =
(w => w.Create(It.IsAny<Widget>()));
widgetCreator.Setup(expressionCreate)
.Callback((Widget widget) => localWidget = widget);
var presenter = new WidgetCreatorPresenter(widgetCreator.Object);
presenter.Save("Name");
widgetCreator.Verify(expressionCreate, Times.Once());
Assert.IsNotNull(localWidget);
Assert.AreEqual("Derived.Name", localWidget.DerivedName);
}
두 번째 방법이 더 바람직하다는 데 동의합니다. Verify를 사용하는 @ aqwert의 제안이 마음에 들지만, 실패 메시지는 사용하기가 너무 어렵습니다. 한 번 표현식을 선언해야하므로 두 번째 방법을 업데이트하는 원래 질문에 몇 가지 코드를 추가했습니다. 나는 그 접근 방식을 고수 할 것이라고 생각한다. – rsbarro