我想测试if-else语句是否被执行,“if”块返回字典/缓存中的项并返回输出,而“else”块将输入添加到缓存中并返回输出< / p>
IModifyBehavior的接口与方法Apply
我能够使用moq正确实现它,但现在我想尝试的是使用stubclass(没有框架)进行单元测试,我也想在不使用fakes的情况下实现它。
我有这个课程:
namespace Decorator
{
using System;
/// <summary>
/// Reverse Behavior
/// </summary>
public class ReverseBehavior : IModifyBehavior
{
/// <summary>
/// Applies the specified value.
/// </summary>
/// <param name="value">The value.</param>
/// <returns>result</returns>
public string Apply(string value)
{
var result = string.Empty;
if (value != null)
{
char[] letters = value.ToCharArray();
Array.Reverse(letters);
result = new string(letters);
}
return result;
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
/// <summary>
/// Caching Decorator
/// </summary>
public class CachingDecorator : IModifyBehavior
{
/// <summary>
/// The behavior
/// </summary>
private IModifyBehavior behavior;
public CachingDecorator(IModifyBehavior behavior)
{
if (behavior == null)
{
throw new ArgumentNullException("behavior");
}
this.behavior = behavior;
}
private static Dictionary<string, string> cache = new Dictionary<string, string>();
/// <summary>
/// Applies the specified value.
/// </summary>
/// <param name="value">The value.</param>
/// <returns>
/// value
/// </returns>
public string Apply(string value)
{
////Key = original value, Value = Reversed
var result = string.Empty;
//cache.Add("randel", "lednar");
if(cache.ContainsKey(value))
{
result = cache[value];
}
else
{
result = this.behavior.Apply(value);// = "reversed";
////Note:Add(key,value)
cache.Add(value, result);
}
return result;
}
}
}
这是我目前的测试代码,代码能够通过测试,但我不确定我的实现是否正确:
[TestClass]
public class CachingDecoratorTest
{
private IModifyBehavior behavior;
[TestInitialize]
public void Setup()
{
this.behavior = new CachingDecorator(new ReverseBehavior());
}
[TestCleanup]
public void Teardown()
{
this.behavior = null;
}
[TestMethod]
public void Apply_Cached_ReturnsReversedCachedValue()
{
string actual = "randel";
////store it inside the cache
string cached = this.behavior.Apply(actual);
////call the function again, to test the else block statement
////Implement DRY principle next time
string expected = this.behavior.Apply(actual);
Assert.IsTrue(cached.Equals(expected));
}
[TestMethod]
public void Apply_NotCached_ReturnsReversed()
{
string actual = "randel";
string expected = "lednar";
Assert.AreEqual(expected, this.behavior.Apply(actual));
}
}
先生/女士,你的答案会有很大的帮助。谢谢++
答案 0 :(得分:2)
我认为你会想要一个真正运用该课程合同的单元测试,而不必担心内部太多。例如,您可以通过反射做一些事情,或者公开一些新方法,允许您的测试向缓存询问它正在做什么,但您的测试无论如何都不应该关心它。如果我看一下缓存装饰器,你暗示的合同是这样的:
使用参数apply
调用x
并返回值v
后,对参数apply
的{{1}}的任何后续调用也将返回{{1} }}
正如您已经拥有的那样,使用x
调用该方法两次的测试可以显示我们两次都返回v
。但我们不能说这是因为缓存装饰器正在做我们想要的,或者是因为底层的反转修改器只是遵循合同。
那么,如果我们有一个不遵守这些规则的基础修饰符呢?
假设使用模拟,您设置了一个x
的实现,它返回了它被调用的次数?现在我们有了不同的行为 - 如果我使用相同的参数v
调用3次这个实现,我会得到3个不同的答案(可以通过单元测试验证)。如果我然后在你的CachingDecorator中包装那个mock,我可以看到CachingDecorator挂起它看到的第一个调用,并遵守原始契约。这向我证明了CachingDecorator的内部遵循合同而不是仅仅将调用传递给恰好遵循合同的其他对象。
答案 1 :(得分:0)
我的第一个问题是你为什么反对使用模拟框架?
但是在这之下工作,为什么不只是滚动你自己的模拟看Rolling your own mock objects,这解决了你的问题而不使用外部库。