0

I am testing a public API however, internally my API is calling a function with signature like

protected internal virtual void AddBook(Book book)
{
    if (null !=book)
        bookList= book;
}

And bookList is also defined as

public virtual BookInformation bookList{ get; protected internal set; }

I need to set this bookList. I can do it either using function AddBook or directly accessing bookList. bookList is also defined as "protected internal set".

I tried

var mockModule = new Mock<myModule> { CallBase = true };
mockModule.Protected()
    .Setup<Book>("AddBook", book);

But I get error that "AddBook" does not exist.

Any ideas what am I missing?

Update I was pressed against deadline so I ended up mocking the class. This solved my problem for now.

BeHappy
  • 138
  • 2
  • 17
  • Not related to the question, but the fact that a single `book` can be assigned to `bookList` (which one would assume to be a *list* of books) is a bit confusing. It also defies the name of the method - it's not *adding* a book, but rather *setting* the list of books. – Rob Jan 18 '17 at 23:20
  • Consider to check here http://stackoverflow.com/questions/17569746/mocking-internal-classes-with-moq-for-unit-testing – Artem Jan 19 '17 at 11:45

2 Answers2

0

When you write.Setup<Book>("AddBook", book); this is mocking a method with a return type of Book, but your return type is void. That's why you get an error that AddBook does not exist. You need to call .Setup("AddBook", book) instead.

To mock a protected member you must first include the following at the top of your test fixture:

using Moq.Protected;

You then call Protected() on your mock, after which you can use the generic Setup<> with the return type of your method.

var mock = new Mock<MyClass>();
mock.Protected()
     .Setup<int>("MyProtectedGetIntMethod")
     .Returns(1);

If the method returns void then use the non-generic Setup().

Panda
  • 6,955
  • 6
  • 40
  • 55
Owen Pauling
  • 11,349
  • 20
  • 53
  • 64
0

According to documentation in the Quickstart

if you need argument matching, you MUST use ItExpr rather than It

// at the top of the test fixture
using Moq.Protected;

// in the test
var mock = new Mock<Invitation> { CallBase = true };

// if you need argument matching, you MUST use ItExpr rather than It
// planning on improving this for vNext
mock.Protected()
    .Setup<Book>("AddBook", ItExpr.IsAny<Book>());
Nkosi
  • 235,767
  • 35
  • 427
  • 472