-1

i have a class extend from a base class,the base class in another dll.

public class MyMicroBlogCache : RelatedBase<THZUserInfo, MicroBlogCacheModel, int>

and in constructor,inject a ICache

public MyMicroBlogCache(ICache cache,....

in base class ,i use the ICache in a method(for example void A() )

and i write a unit test,mock the ICache

var cache = Substitute.For<ICache>();
cache.PageRelated<THZUserInfo, MicroBlogCacheModel, int>("My", 2217, 0, 3, out all, true)
.Returns(
    x =>
    {
        var list = new List<MicroBlogCacheModel>();
        list.Add(new MicroBlogCacheModel { Id = 1, UserId = 2217 });
        list.Add(new MicroBlogCacheModel { Id = 1, UserId = 2217 });
        list.Add(new MicroBlogCacheModel { Id = 1, UserId = 2217 });
        return list;
    });

mock with NSubstitute

var cache1 = new Mock<ICache>();
cache1.Setup(ca => ca.PageRelated<THZUserInfo, MicroBlogCacheModel, int>("My", 2217, 0, 3, out all, true))
.Returns(
() =>
{
    var list = new List<MicroBlogCacheModel>();
    list.Add(new MicroBlogCacheModel { Id = 1, UserId = 2217 });
    list.Add(new MicroBlogCacheModel { Id = 1, UserId = 2217 });
    list.Add(new MicroBlogCacheModel { Id = 1, UserId = 2217 });
    return list;
});

or mock with moq

and the strange thing is:
when i call the method write in base class(RelatedBase),the method(for example A()) call mock ICache,it not return the mock data.
if i override the method in child class(MyMicroBlogCache),and use the same code(override and copy the code from base class),it return the mock data.
if i override,and use base.A(...) ,it not return mock data.
so,when the code in base class,it wrong,and when code in child class,it right.
if i create a class implement ICache,it is ok
both NSubstitute and Moq are same.
i try this with vs2015,vs2013;.net 4.5
why it happens,and how can i fix it

Update:

        var cache1 = new Mock<ICache>(MockBehavior.Strict);
        cache1.Setup(ca => ca.PageRelated<THZUserInfo, MicroBlogCacheModel, int>("My", 2217, 0, 3, out all, true))
            .Returns(
            () =>
            {
                var list = new List<MicroBlogCacheModel>();
                list.Add(new MicroBlogCacheModel { Id = 1, UserId = 2217 });
                list.Add(new MicroBlogCacheModel { Id = 1, UserId = 2217 });
                list.Add(new MicroBlogCacheModel { Id = 1, UserId = 2217 });
                return list;
            });

then test method call

var r = my.GetRelatedPage(2217, 0, 3, out all, true);

in base class it call

var list = cache.PageRelated<TMainKey, TChild, TMainKey>("My", key, skip, take, out all, desc);

key=2217,skip=0,take=3,desc=true,

chenZ
  • 920
  • 4
  • 16

1 Answers1

0

You have a generic base class:

RelatedBase<T1, T2, T3>

you also have an inherited class without generic parameters, which specifies the type for each T1, T2, T3.

With genericity, RelatedBase<THZUserInfo, MicroBlogCacheModel, int> is not the same type as RelatedBase<T1, T2, T3>

Now: In your set-up, you explicitly Setup ca.PageRelated<THZUserInfo, MicroBlogCacheModel, int>

If, you call the method on the base class (the generic one) with different argument types, then it will not exactly be the same call as the one which was setup, and therefore, will return the default value for the method.

Try instantiating your Mock with new Mock<ICache>(MockBehavior.MockStrict) and you should have a MockException that confirms that.

Then, think of type arguments as proper arguments : if they don't match, then the setup doesn't apply.

Hope this helps :)

Fabio Salvalai
  • 2,479
  • 17
  • 30