我正在使用TypeMock Isolater来模拟某些单元测试的某些对象 - 尝试使用AAA api(所以使用Isolate调用)。
我有一个简单的单例类,您可以在其中调用静态GetInstance(),然后返回该类的实例。我认为这很简单,但是我遇到了一个非常令人沮丧的问题!我似乎无法使GetInstance()正确地使用我预期的调用设置返回我的模拟对象。
我试过了:
我想要的只是模拟一个单例,并且我没有明确告诉它期望抛出异常的任何调用。我觉得这很简单,但显然不是!悲伤
有谁知道我做错了什么?
由于 詹姆斯
答案 0 :(得分:3)
我认为简单的解决方案是创建一个单例类的假实例,并在调用实际的类构造函数之前使用SwapNextInstace:
[TestMethod]
public void SetBhaciorOnSingleton()
{
var fake = Isolate.Fake.Instance<SingletonClass>();
Isolate.WhenCalled(() => fake.SomeFunction()).WillReturn(10);
// Set additional behavior on singleton class
Isolate.Swap.NextInstance<SingletonClass>().With(fake);
// This is where the class constructor is being called
var result = SingletonClass.GetInstace().SomeFunction();
Assert.AreEqual(10, result );
}
除非在测试之前创建单例类,否则此解决方案应适用于大多数场景。 如果您需要在创建类之后设置行为,请使用WhenCalled:
[TestMethod]
public void SetBhaciorOnSingleton()
{
var fake = Isolate.Fake.Instance<SingletonClass>();
Isolate.WhenCalled(() => fake.SomeFunction()).WillReturn(10);
Isolate.WhenCalled(() => SingletonClass.GetInstace()).WillReturn(fake);
var result = SingletonClass.GetInstace().SomeFunction();
Assert.AreEqual(10, result );
}
答案 1 :(得分:2)
免责声明我在Typemock工作。
您无需模拟Singleton.GetInstance&lt;&gt;()。使用Isolate.Fake.AllInstances&lt;&gt;()而不是Isolate.Fake.Instance&lt;&gt;()可以模拟单例。然后通过设置应用于所有实例的伪单例行为的行为。
看看这个例子:
public class Singleton
{
private Singleton() { }
static readonly Singleton instance = new Singleton();
public static Singleton Instance { get { return instance; } }
public int ReturnZero()
{
return 0;
}
}
[TestMethod]
public void FakeSingleton()
{
// Here we are setting the same behavior on all instances.
// The behavior we set on fake will apply to past instance as well
var fakeSingleton = Isolate.Fake.AllInstances<Singleton>();
Isolate.WhenCalled(() => fakeSingleton.ReturnZero()).WillReturn(10);
// Assert that the behavior works.
Assert.AreEqual(10, Singleton.Instance.ReturnZero());
}
答案 2 :(得分:0)
感谢。
之前我没有尝试过NextInstance,因为它不适用于我不想改变的接口。
但是,我已经尝试了它确实有效 - 尽管我假设设置的顺序当时遇到的问题并不重要,但它肯定会这样做。例如,如果我在Swap之后执行WhenCalled,它就不起作用。它需要在Swap之前进行。 (说实话,对我来说真的没有意义 - 它应该是同一个对象)。
但是,最后一个例子(我试过的方法之一)对我不起作用。我假装,在假设置expecation,然后在Singleton上设置期望返回伪造的实例 - 但现在它返回具体的实例!
它是否与构造函数的调用方式有关?我记得有过这样的事情......
或者我可以使用Swap,但是,我希望能够在TestSetup中设置所有这些东西,并对实际测试中的期望进行微小修改,但这看起来不太可能。 ?
答案 3 :(得分:-2)
最好的解决方案是不使用单例(或任何其他静态可变数据)。只需创建一个实例并使用依赖注入将其传递给所有需要它的对象。