通过接口引入对象以模拟它
Bring object through interface in order to mock it
我正处于面临以下问题的十字路口。比方说,我有以下 class
public class Foo
{
internal Bar bar { get; }
internal Foo(Bar bar)
{
this.bar = bar;
}
}
我正在尝试使用 XUnit 和 Moq 对其进行单元测试。我创建的初始测试是
[Theory]
[AutoMockData]
internal void CtorShouldCreateInstance(Bar bar)
{
var sut = new Foo(bar);
Assert.NotNull(sut);
}
这是一个有效的单元测试,但是通过将 Bar 作为参数传递,它带来了所有依赖项,使其成为 concrete 类型.我同事的建议是通过 Interface 和 Mock 接口带来 Bar 对象,但我我不知道该怎么做。
我想过制作接口,CreateBar 的方法及其所需参数,继承 Foo 的接口 class,实现该方法,然后将其添加到单元测试中,但我想得到澄清或批准,因为我不确定这是正确的方法。
在此先感谢您的帮助!
你必须从 IBar 派生出 Bar,这样你就可以使用像 FakeItEasy 这样的 Mocking 框架轻松地 Mock 它,这里是一个例子:
public interface IBar
{
string SayHello();
}
public class Bar : IBar
{
public string SayHello()
{
// A complex work to retrieve data from external resource
return "Hello";
}
}
public class Foo
{
private readonly IBar _bar;
public Foo(IBar bar)
{
_bar = bar;
}
public string Greeting()
{
return _bar.SayHello();
}
}
现在您可以模拟 IBar 以 return 您想要的结果:
[TestFixture]
public class FooTests
{
[Test]
public void Bar_ShouldReturn_HiInsteadOfHello()
{
IBar fakeBar = A.Fake<IBar>();
A.CallTo(() => fakeBar.SayHello()).Returns("Hi");
Foo sut = new Foo(fakeBar);
Assert.AreEqual(sut.Greeting(), "Hi");
}
}
* 旁注: 您也可以直接模拟您的方法,而无需通过将其设为虚拟来从接口派生该方法,但作为最佳实践,最好改用接口:
public class Bar
{
public virtual string SayHello()
{
// A complex work to retrieve data from external resource
return "Hello";
}
}
public class Foo
{
private readonly Bar _bar;
public Foo(Bar bar)
{
_bar = bar;
}
public string Greeting()
{
return _bar.SayHello();
}
}
[TestFixture]
public class FooTests
{
[Test]
public void Bar_ShouldReturn_HiInsteadOfHello()
{
Bar fakeBar = A.Fake<Bar>();
A.CallTo(() => fakeBar.SayHello()).Returns("Hi");
Foo sut = new Foo(fakeBar);
Assert.AreEqual(sut.Greeting(), "Hi");
}
}
显然我所要做的就是传递 IBar 接口作为参数而不是正常的 Bar class ,因为 AutoMockData 处理了一切。
所以是的,答案是使 Foo class
public class Foo
{
internal IBar bar { get; }
internal Foo(Bar bar)
{
this.bar = bar;
}
}
测试变成
[Theory]
[AutoMockData]
internal void CtorShouldCreateInstance(IBar bar)
{
var sut = new Foo(bar);
Assert.NotNull(sut);
}
感谢大家的帮助!
我正处于面临以下问题的十字路口。比方说,我有以下 class
public class Foo
{
internal Bar bar { get; }
internal Foo(Bar bar)
{
this.bar = bar;
}
}
我正在尝试使用 XUnit 和 Moq 对其进行单元测试。我创建的初始测试是
[Theory]
[AutoMockData]
internal void CtorShouldCreateInstance(Bar bar)
{
var sut = new Foo(bar);
Assert.NotNull(sut);
}
这是一个有效的单元测试,但是通过将 Bar 作为参数传递,它带来了所有依赖项,使其成为 concrete 类型.我同事的建议是通过 Interface 和 Mock 接口带来 Bar 对象,但我我不知道该怎么做。
我想过制作接口,CreateBar 的方法及其所需参数,继承 Foo 的接口 class,实现该方法,然后将其添加到单元测试中,但我想得到澄清或批准,因为我不确定这是正确的方法。
在此先感谢您的帮助!
你必须从 IBar 派生出 Bar,这样你就可以使用像 FakeItEasy 这样的 Mocking 框架轻松地 Mock 它,这里是一个例子:
public interface IBar
{
string SayHello();
}
public class Bar : IBar
{
public string SayHello()
{
// A complex work to retrieve data from external resource
return "Hello";
}
}
public class Foo
{
private readonly IBar _bar;
public Foo(IBar bar)
{
_bar = bar;
}
public string Greeting()
{
return _bar.SayHello();
}
}
现在您可以模拟 IBar 以 return 您想要的结果:
[TestFixture]
public class FooTests
{
[Test]
public void Bar_ShouldReturn_HiInsteadOfHello()
{
IBar fakeBar = A.Fake<IBar>();
A.CallTo(() => fakeBar.SayHello()).Returns("Hi");
Foo sut = new Foo(fakeBar);
Assert.AreEqual(sut.Greeting(), "Hi");
}
}
* 旁注: 您也可以直接模拟您的方法,而无需通过将其设为虚拟来从接口派生该方法,但作为最佳实践,最好改用接口:
public class Bar
{
public virtual string SayHello()
{
// A complex work to retrieve data from external resource
return "Hello";
}
}
public class Foo
{
private readonly Bar _bar;
public Foo(Bar bar)
{
_bar = bar;
}
public string Greeting()
{
return _bar.SayHello();
}
}
[TestFixture]
public class FooTests
{
[Test]
public void Bar_ShouldReturn_HiInsteadOfHello()
{
Bar fakeBar = A.Fake<Bar>();
A.CallTo(() => fakeBar.SayHello()).Returns("Hi");
Foo sut = new Foo(fakeBar);
Assert.AreEqual(sut.Greeting(), "Hi");
}
}
显然我所要做的就是传递 IBar 接口作为参数而不是正常的 Bar class ,因为 AutoMockData 处理了一切。
所以是的,答案是使 Foo class
public class Foo
{
internal IBar bar { get; }
internal Foo(Bar bar)
{
this.bar = bar;
}
}
测试变成
[Theory]
[AutoMockData]
internal void CtorShouldCreateInstance(IBar bar)
{
var sut = new Foo(bar);
Assert.NotNull(sut);
}
感谢大家的帮助!