I'm trying to get a mocked object property. During the initialization, 'child' class is getting a reference to a parent's private function. I'd like to catch this reference during testing to check parent's private method.
This is a simplified example of much more complex code:
class Monkey{
final name;
final Perk _perk;
Monkey('Maya', this._perk){
this._perk.jump = this._jump;
}
void _jump(int a){ // here's the problem, not able to test private method
print('jump ${a}');
}
}
All I want to do is to be able to test private method _jump during testing in mockito. I don't want to change the code.
During test I created
class MockPerk extends Mock implements Perk{}
Monkey(mockedPerk);
What I want to achieve is:
Create Monkey instance with mockedPerk
Capture property _perk.jump in MockedPerk class
Get reference to private _jump method of Moneky's class to be able to test it.
Limitation
Making method public is not an option.
Making method public with #visibleForTesting is not an option
You can capture values passed to setters with verify(mock.setter = captureAny). For example:
var mockedPerk = MockPerk();
var monkey = Monkey('Maya', mockedPerk);
var jump = verify(mockedPerk.jump = captureAny).captured.single as void
Function(int);
jump(5); // Prints: jump 5
Related
Consider the following code (in C# but it could be any other language):
public interface IObjectCopier
{
void Copy<T>(T source, T target);
}
public class Model
{
public string Name { get; set; }
}
public class ViewModel
{
private readonly IObjectCopier _objectCopier;
public ViewModel(IObjectCopier objectCopier)
{
_objectCopier = objectCopier;
}
public Model ViewBindData { get; set; }
public void Load(Model model)
{
_objectCopier.Copy(model, ViewBindData);
}
}
How do I construct a unit test for the Load method? If I mock IObjectCopier then I need to supply a mock implementation of the Copy method. In this example it is trivial but in a real world scenario Model can be large with sub models and the mocking exercise feel like it is just copying what the IObjectCopier implementation does.
The problem is simplified if I could change the Copy method to the following:
T Copy<T>(T source);
As in this case the mock setup is drastically simplified. The problem is that there are view bindings to the Model object and I cannot simply destroy and re-create the object.
Is there an elegant way to get around this problem?
If you're using mocks, then the only thing you care about is that the copier is invoked with the 2 parameters.
So in some sort of pseudo code
test "populates model from view data" {
objectCopiermock = mock(IObjectCopier)
model = new Model() //create empty or use a TestDataBuilder
viewBindData = new viewBindData() //create empty or use a TestDataBuilder
viewModel = new ViewModel(objectCopiermock)
viewModel.viewBindData(viewBindData)
viewModel.Load(model)
verifyMock(objectCopiermock).copy(model, viewBindData)
}
The important thing with mocks is to verify the interactions, and not the values inside model or viewBindData.
If this is confused, don't panic! (tm) - and I would suggest you to read a bit about the difference between the London and Chicaco/Detroit schools of TDD
I am new to FakeItEasy and try solve a problem.
I have a class
public class Events
{
public List<Events> SaveEvents()
{
// Call to repository and return 1(success) or -1(fail)
//If the repository return 1 then need to make another call to save the action in db
//Sample Code here
AuditLogService log = new AuditLogService();
log.CallLog();
}
}
Here is the Test Code:
[TestMethod]
public void EventValidation()
{
//Arrange
var Fakeevents = A.Fake<Events>();
var log = A.Fake<AuditLogService>();
var _EventsController = new EventsController(Fakeevents);
_EventsController.SaveEvents();
A.CallTo(
() => Fakeevents.SaveEvents().Retunr(1).AssignsOutAndRefParameters(status)
A.CallTo(
() => log.CallLog()).MustHaveHappened(Repeated.AtLeast.Once);
}
I am getting error like "Non virtual methods can not be intercepted"
I want to check whether the Calllog method is called after success or not.
Can anyone please help me on this.
I have a method and inside a method i am initiating another class and calling a method of the class. I want to check from fakeItEasy whether the method is called.
Unfortunately, your title says it all. Non-virtual members cannot be faked, configured, or intercepted, as noted in the documentation under "What members can be overridden?".
There's nothing that FakeItEasy can do for you unless you make the member virtual (or promote it to an interface and fake the interface, or something similar).
Have you tried to use function?
Like this:
Func<YourReturnType> action = () => YourMethod(params); // Act
action.Should().Throw<Exception>(); // Assert
var log = A.Fake();
Use interface instead of AuditLogService. And have this class implement that interface
var log = A.Fake();
I'm following the accepted answer in this question but I'm getting a NullReferenceException.
What I need is having a partial mock stub a property (both getter and setter) to behave like a stub (as a simple automatic property). Currently I am able to stub the getter but not the setter.
Is this possible?
EDIT: this is a simple example, I hope it helps explaining my problem.
public class SomeClass
{
public virtual string SomeProperty
{
get{ return SomeMethodDependingOnDBOrAspSession(); }
set{ SomeMethodDependingOnDBOrAspSession(value); } // I want to avoid calling this setter implementation
}
}
var partialMock = MockRepository.GeneratePartialMock<SomeClass>();
partialMock.Stub(p => p.SomeProperty); // I want SomeProperty to behave as an automatic property
When using a PartialMock you can get auto-implemented property like behavior by using PropertyBehavior feature of Rhino Mocks. Given the class in your question, the following nunit test passes for me.
[Test]
public void TestPartialMock()
{
var someClass = MockRepository.GeneratePartialMock<SomeClass>();
someClass.Stub(x => x.SomeProperty).PropertyBehavior();
string val = "yo!";
Assert.DoesNotThrow(() => someClass.SomeProperty = val);
Assert.AreEqual(val, someClass.SomeProperty);
}
If you don't need a PartialMock you could use a Stub which has property behavior by default. You'd simply replace the first two lines of the test with:
var someClass = MockRepository.GenerateStub<SomeClass>();
I have a public method that uses a local private method to get data from the Db.
private string SomeMethod(string)
{
...
Doing some operations
...
string data = GetDBData(string);
Doing some operations
...
}
I want to divert/isolate the private method GetDBData(string) using moles so my test will not require the DB.
Obviously, my question is: how to do it?
thank you
Uria
EDIT
Additional information:
i tried to change the method accessors both to public and internal protected,
in both cases i can now see the methods as moles.
BUT when running the test, the original method is still being used and not the detour I've implemented in the PexMethod.
You can try any of the following.
Make the method internal and add an attribute like this to the assembly:
[assembly: InternalsVisibleTo("<corresponding-moles-assembly-name>")]
Change the method access to protected virtual and then use a stub.
Refactor your class so that it gets an interface (IDataAccessObject) as a constructor parameter, SomeMethod being one of the methods of that interface, and then pass a stub of that interface to your class in test methods.
I figured it out
If i have the public MyClass with private SomeMethod
public class MyClass
{
private string SomeMethod(string str){}
}
if you want to mole the SomeMethod method you need to use AllInstances in the test method:
[PexMethod]
SomeMethod(string str)
{
MMyClass.AllInstances.SomeMethod = (instance, str) => { return "A return string"; };
}
notice that the lambda receives an instance parameter as the first parameter. I'm not sure what it's function is.
I am trying to unit test an action filter I wrote. I want to mock the HttpClientCertificate but when I use MOQ I get exception. HttpClientCertificate doesnt have a public default constructor.
code:
//Stub HttpClientCertificate </br>
var certMock = new Mock<HttpClientCertificate>();
HttpClientCertificate clientCertificate = certMock.Object;
requestMock.Setup(b => b.ClientCertificate).Returns(clientCertificate);
certMock.Setup(b => b.Certificate).Returns(new Byte[] { });
This is the most awkward case of creating unit testable systems in .NET. I invariable end up adding a layer of abstraction over the component that I can't mock. Normally this is required for classes with inaccessible constructors (like this case), non-virtual methods or extension methods.
Here is the pattern I use (which I think is Adapter pattern) and is similar to what MVC team has done with all the RequestBase/ResponseBase classes to make them unit testable.
//Here is the original HttpClientCertificate class
//Not actual class, rather generated from metadata in Visual Studio
public class HttpClientCertificate : NameValueCollection {
public byte[] BinaryIssuer { get; }
public int CertEncoding { get; }
//other methods
//...
}
public class HttpClientCertificateBase {
private HttpClientCertificate m_cert;
public HttpClientCertificateBase(HttpClientCertificate cert) {
m_cert = cert;
}
public virtual byte[] BinaryIssuer { get{return m_cert.BinaryIssuer;} }
public virtual int CertEncoding { get{return m_cert.CertEncoding;} }
//other methods
//...
}
public class TestClass {
[TestMethod]
public void Test() {
//we can pass null as constructor argument, since the mocked class will never use it and mock methods will be called instead
var certMock = new Mock<HttpClientCertificate>(null);
certMock.Setup(cert=>cert.BinaryIssuer).Returns(new byte[1]);
}
}
In your code that uses HttpClientCertificate you instead use HttpClientCertificateBase, which you can instantiate like this - new HttpClientCertificateBase(httpClientCertificateInstance). This way you are creating a test surface for you to plug in mock objects.
The issue is that you need to specify constructor parameters when creating the mock of the HttpClientCertificate.
var certMock = new Mock<HttpClientCertificate>(ctorArgument);
The bad news is that the ctor for HttpClientCertificate is internal and takes in an HttpContext, so it probably won't work.
Unless you want to write more code to make the class "Testable" I suggest you use Typemock Isolator, Unless specified otherwise it looks for the first c'tor available - public, internal or private and fake (mocks) it's parameters so you won't have to.
Creating the fake object is as simple as:
var fakeHttpClientCertificate = Isolate.Fake.Instance<HttpClientCertificate>();
Another alternative is to use the free Microsoft Moles framework. It will allow you to replace any .NET method with your own delegate. Check out the link as it gives an example that is pretty easy to understand. I think you'll find it much nicer than adding layers of indirection to get HttpClientCertificate into a testable state.