2017-09-27 91 views
1

我有一个问题,在我的测试用例中,我试图嘲笑我的ICacheProvider的返回,但它总是返回nullNSubstitute ReturnsForAnyArgs返回null,但不应该

[Fact] 
public void Raise_ShoultReturnTrue_IfItsInCache() 
{ 
    var cacheProvider = Substitute.For<ICacheProvider>(); 
    cacheProvider.Fetch(Arg.Any<string>(), default(Func<IEnumerable<int>>)).ReturnsForAnyArgs(GetFakeCacheDB()); 

    //I was expecting the var below to contain the data from GetFakeCacheDB method 
    var cacheProviderReturn = cacheProvider.Fetch("anything", returnEmpty); 

    //there is more stuff here but doesnt matter for the question  
} 

private HashSet<int> returnEmpty() 
{ 
    return new HashSet<int>(); 
} 

private IEnumerable<int> GetFakeCacheDB() 
{ 
    var cacheData = new List<int>() 
        { 
         57352, 
         38752 
        };  
    return cacheData; 
} 

public interface ICacheProvider 
{ 
    void Add<T>(string key, T item); 
    void Add<T>(string key, T item, DateTime? absoluteExpiry, TimeSpan? relativeExpiry); 
    T Fetch<T>(string key, Func<T> dataLookup); 
    T Fetch<T>(string key, Func<T> dataLookup, DateTime? absoluteExpiry, TimeSpan? relativeExpiry); 
    void Remove<T>(string key); 
} 

我的测试用例有什么问题?

回答

1

mocked方法的参数的配置期望与传递给它的内容不匹配,所以它将返回null。

您目前的期望值为default(Func<IEnumerable<int>>),默认为null,但在模拟中,您传递的实际函数与配置的期望值不符。

使用Arg.Any以及第二个参数,以使模拟期望值在执行时更加灵活。

cacheProvider 
    .Fetch(Arg.Any<string>(), Arg.Any<Func<IEnumerable<int>>>()) 
    .ReturnsForAnyArgs(GetFakeCacheDB()); 
+0

谢谢您的回答,它工作时,我改变方法的签名 “的HashSet returnEmpty()” 到 “IEnumerable的 returnEmpty()” – TiagoM

1

测试失败的原因是因为存根调用与实际运行的调用不同。这是很难看到,因为一般的说法,但如果你明确地指定他们,你会得到这样的事情:

// Arrange 
cacheProvider.Fetch<IEnumerable<int>>(/* ... */).ReturnsForAnyArgs(GetFakeCacheDB()); 
// Act 
var cacheProviderReturn = cacheProvider.Fetch<HashSet<int>>("anything", returnEmpty); 

.NET看到Fetch<IEnumerable<int>>()Fetch<HashSet<int>>作为两种不同的方法,因此,尽管第一线一直对于任何参数存留为返回GetFakeCacheDB(),第二种方法尚未配置并且将返回null。有关更多说明,请参阅this post

要使测试按预期工作,请确保通用呼叫签名匹配,无论是通过明确指定通用名称,还是确保传递的参数都是正确的通用名称。

// Option 1: explicit generic 
var cacheProviderReturn = cacheProvider.Fetch<IEnumerable<int>>("anything", returnEmpty); 
// where `returnEmpty` is `Func<HashSet<int>>` 

// Option 2: keep stubbed call the same, and change `returnEmpty` return type 
// from `HashSet<int>` to `IEnumerable<int>` to make sure it results 
// in correct generic being called. 
private IEnumerable<int> returnEmpty() { 
    return new HashSet<int>(); 
} 
相关问题