C# 如何验证XUnit Moq中的执行顺序?
我有以下课程:C# 如何验证XUnit Moq中的执行顺序?,c#,unit-testing,moq,xunit,xunit.net,C#,Unit Testing,Moq,Xunit,Xunit.net,我有以下课程: public class Foo { public int Prop1 { get; set; } public string Prop2 { get; set; } public Stream TestStream; public WriteToTestStream() { ... } } WriteToTestStream写入TestStream 我想写一个单元测试来确保 Prop1和Prop2在写入TestStream 一旦将某
public class Foo
{
public int Prop1 { get; set; }
public string Prop2 { get; set; }
public Stream TestStream;
public WriteToTestStream()
{ ... }
}
WriteToTestStream
写入TestStream
我想写一个单元测试来确保
Prop1
和Prop2
在写入TestStream
TestStream
,就不应该访问这些属性WriteToTestStream
定义模拟?
如何从模拟函数中操作局部变量(我可以在单元测试中使用局部变量来记住何时写入流/设置属性)?一种方法是保留局部状态变量,然后使用Moq回调来跟踪状态,您可以在回调中断言,以确保状态正确。这里有一个例子(尽管是在努尼特)。我还假设您实际上想要测试以正确顺序使用
Foo
的SUT(我在这里调用了SUTBar
)
另一种方法是使用,尽管我必须承认我还没有用过
编辑
似乎MockSequence
(insesequence
)具有,尽管这可能会强制执行非常严格的序列,并且似乎还需要:
[TestFixture]
公共类单元测试
{
私人模拟(mockFoo),;
[设置]
公共作废设置()
{
_mockFoo=newmock(MockBehavior.Strict);
var seq=新的模拟序列();
_mockFoo.InSequence(seq).SetupSet(m=>m.Prop1=It.IsAny());
_mockFoo.InSequence(seq).SetupSet(m=>m.Prop2=It.IsAny());
_mockFoo.InSequence(seq).Setup(m=>m.WriteToTestStream());
}
[测试]
公共秩序
{
var sut=新条(_mockFoo.Object);
Assert.doesnothrow(()=>sut.doSomethingOrder());
}
[测试]
公共无效保证自动福特()
{
var sut=新条(_mockFoo.Object);
Assert.Catch(()=>sut.DoSomethingOutOfOrder());
}
}
谢谢你,斯图尔特。回调的解决方案适合我。不过,我认为有一个不连贯的问题。我读到它对同一个模拟对象不起作用老实说,我没有发现很多情况下需要验证调用依赖项方法的顺序(在我看来,这通常是白盒/实现细节)。但是,为了提供返回数据序列,我通常使用ReturnsInOrder
扩展名
[TestFixture]
public class UnitTest
{
private bool _prop1Set = false;
private bool _prop2Set = false;
private Mock<IFoo> _mockFoo;
[SetUp]
public void Setup()
{
_mockFoo = new Mock<IFoo>();
_mockFoo.SetupSet(m => m.Prop1).Callback(i => _prop1Set = true);
_mockFoo.SetupSet(m => m.Prop2).Callback(s => _prop2Set = true);
_mockFoo.Setup(m => m.WriteToTestStream())
.Callback(() => Assert.IsTrue(_prop1Set && _prop2Set));
}
[Test]
public void EnsureInOrder()
{
var sut = new Bar(_mockFoo.Object);
Assert.DoesNotThrow(() => sut.DoSomethingInOrder());
}
[Test]
public void EnsureOutOfOrder()
{
var sut = new Bar(_mockFoo.Object);
Assert.Catch<Exception>(() => sut.DoSomethingOutOfOrder());
}
}
public interface IFoo
{
int Prop1 { get; set; }
string Prop2 { get; set; }
void WriteToTestStream();
}
public class Foo : IFoo
{
public int Prop1 { get; set; }
public string Prop2 { get; set; }
// Surely this is internal implementation
private Stream TestStream;
public void WriteToTestStream() { }
}
public class Bar
{
private readonly IFoo _foo;
public Bar(IFoo injectedFoo)
{
_foo = injectedFoo;
}
public void DoSomethingInOrder()
{
_foo.Prop1 = 1;
_foo.Prop2 = "Baz";
_foo.WriteToTestStream();
}
public void DoSomethingOutOfOrder()
{
_foo.WriteToTestStream();
_foo.Prop2 = "Baz";
_foo.Prop1 = 1;
}
}
[TestFixture]
public class UnitTest
{
private Mock<IFoo> _mockFoo;
[SetUp]
public void Setup()
{
_mockFoo = new Mock<IFoo>(MockBehavior.Strict);
var seq = new MockSequence();
_mockFoo.InSequence(seq).SetupSet(m => m.Prop1 = It.IsAny<int>());
_mockFoo.InSequence(seq).SetupSet(m => m.Prop2 = It.IsAny<string>());
_mockFoo.InSequence(seq).Setup(m => m.WriteToTestStream());
}
[Test]
public void EnsureInOrder()
{
var sut = new Bar(_mockFoo.Object);
Assert.DoesNotThrow(() => sut.DoSomethingInOrder());
}
[Test]
public void EnsureOutOfOrder()
{
var sut = new Bar(_mockFoo.Object);
Assert.Catch<MockException>(() => sut.DoSomethingOutOfOrder());
}
}