Thanks for providing your code. I think I have a much better handle on what you're trying to do now.
For your ShouldNotAcceptInvalidUser
test, you should definitely mock IMembershipService
instead of AccountMembershipService
(choose option 1 over option 2). Since your controller is your SUT, it should be the only "real" class in the test, in order to minimize the number of moving parts.
With option 1, there's no reason to expect that MembershipService.ValidateUser
would step into any code. The MembershipService
is a mock object - and you've explicitly told it to just always return false
when that method is called. Based on the code here, and using option 1, I'd expect this test to pass.
In your other test, ExampleForMockingAccountMembershipService
, you're mocking your SUT which is something you should not do. Your SUT should be the only "real" object in your test. That means all collaborating objects should be mocked, leaving the SUT to be the only object doing anything meaningful. (That way, if the test fails, you know for sure that it's because of a bug in the SUT.)
(Note: ValidateUser
was always returning true
here because you mocked the SUT, and explicitly told it to always return true
. This is why it's never a good idea to mock your SUT - mocking changes the behavior that you're trying to test.)
Based on the code you provided, I'm guessing that the reason you mocked CustomMembershipProvider
is because it doesn't fully implement its abstract base class MembershipService
. If this is indeed the case, then you will need to implement the missing methods manually, instead of relying on the mocking framework to provide default implementations.
Here is what I believe you were intending this test to look like:
[Test]
public void ExampleForMockingAccountMembershipService()
{
var validUserName = "connorgerv";
var validPassword = "passwordd1";
var sut = new CustomMembershipProvider();
Assert.IsTrue(sut.ValidateUser(validUserName, validPassword));
}
Something to look out for here is the fact that CustomMembershipProvider
instantiates one of its dependencies: UsersContext
. In a unit test, since CustomMembershipProvider
is your SUT, you'd want to mock all of its dependencies. In this situation, you could use dependency injection to pass an object responsible for creating this dependency (e.g., an IUsersContextFactory
), and use a mock factory and context in your test.
If you don't want to go that route, then just be aware that your test could fail because of a bug in CustomMembershipProvider
or a bug in UsersContext
.
So, the general logic in your tests is sound; the problems mainly stem from confusion on the role of mock objects in your tests. It's kind of a tough concept to get at first, but here are some resources that helped me when I was learning this: