I ma writing unit testcases using NUnit and Fake it Easy for MVC4 Controllers.
In one of the controller, I should be getting exception.
ExceptionDetail exception = new ExceptionDetail() { Description = "Test", ErrorCode = ExceptionErrorCode.UserIsDisabled };
Exception ex = new Exception(new Uri("http://localhost//Plat/ManagementSvc/Groups?UserID=" + iD "), exception );
A.CallTo(() => Fake.GetDataAsync<IEnumerable<Group>>(fakeHttpSession, url)).Throws(ex);
My question is instead of passing localhost(new Uri("http://localhost//Plat/ManagementSvc/Groups"), is there a way to fake the url for URI
If the problem is that the exception isn't being thrown when your production code calls GetDataAsync, it could just be that your code is passing in a different Uri. If this is so, you can change which Uri triggers that call by using a different form of argument constraint.
Instead of matching the Uri exactly, you could choose to match any Uri:
A.CallTo(() => Fake.GetDataAsync<IEnumerable<Group>>(fakeHttpSession, A<Uri>.Ignored))
.Throws(ex);
Or you could even be more specific:
A.CallTo(() => Fake.GetDataAsync<IEnumerable<Group>>(fakeHttpSession, A<Uri>.That.Matches(uri => uri.AbsolutePath == "/Plat/ManagementSvc/Groups"))
.Throws(ex);
if that's what's needed. There are many options. Check out the documentation.
Note that there's no faking of a Uri here. You're just telling FakeItEasy what tests to apply to a received Uri in order to decide whether the faked GetDataAsync method should throw
Related
Using version 7.3.0 of FakeItEasy.
In following code I am getting message that call to method GetById is not configured, yet I am configuring it. What I am doing wrong?
There is no overload for the GetById method.
var fakeConnection = A.Fake<IEventStoreConnection>();
var fakeResolver = A.Fake<IEventResolver>();
var logger = A.Fake<ILogger<DummyAggregateRepository>>();
var repository = new DummyAggregateRepository(fakeConnection, fakeResolver, logger);
var fakeRepository = A.Fake<DummyAggregateRepository>(
o =>
{
o.Wrapping(repository);
o.Strict();
});
var aggregateId = Guid.NewGuid();
A.CallTo(() => fakeRepository.GetById(aggregateId, A<CancellationToken>._))
.CallsWrappedMethod();
var fixture = new AutoFixture.Fixture();
var events1 = fixture.CreateMany<DummyAggregate.EventOne>(10).Cast<Event>();
var events2 = fixture.CreateMany<DummyAggregate.EventTwo>(10).Cast<Event>();
var events = events1.Union(events2).ToList();
A.CallTo(
() => fakeRepository.GetEvents(
"dummyAggregate-" + aggregateId.ToString("N"),
aggregateId.ToString(),
A<CancellationToken>._))
.Returns(events);
var aggregate = await fakeRepository.GetById(aggregateId, default);
GetById implementation is virtual method
public virtual async Task<TAggregate> GetById(Guid aggregateId, CancellationToken ct)
{
ct.ThrowIfCancellationRequested();
var streamName = this.GetStreamName(aggregateId);
using var scope = EventStoreCommon.CreateScope(Tracer.Instance, nameof(this.GetById), streamName);
var events = await this.GetEvents(streamName, aggregateId.ToString(), ct);
if (events.Any() == false)
{
throw new AggregateNotFoundException(aggregateId, typeof(TAggregate));
}
var aggregate = new TAggregate();
foreach (var #event in events)
{
aggregate.ApplyEvent(#event);
}
return aggregate;
}
Error reported
FakeItEasy.ExpectationException: Call to unconfigured method of strict fake: MyCompany.EventStore.Test.AggregateRepositoryTests.DummyAggregateRepository...
FakeItEasy.ExpectationException
Call to unconfigured method of strict fake: MyCompany.EventStore.Test.AggregateRepositoryTests.DummyAggregateRepository.GetById(aggregateId: d8d0445d-7f82-4636-82fc-2e8f14be7f3d, ct: System.Threading.CancellationToken).
at FakeItEasy.Core.StrictFakeRule.Apply(IInterceptedFakeObjectCall fakeObjectCall) in C:\projects\fakeiteasy\src\FakeItEasy\Core\StrictFakeRule.cs:line 53
at FakeItEasy.Core.FakeManager.ApplyBestRule(IInterceptedFakeObjectCall fakeObjectCall) in C:\projects\fakeiteasy\src\FakeItEasy\Core\FakeManager.cs:line 276
at FakeItEasy.Core.FakeManager.FakeItEasy.Core.IFakeCallProcessor.Process(InterceptedFakeObjectCall fakeObjectCall) in C:\projects\fakeiteasy\src\FakeItEasy\Core\FakeManager.cs:line 178
at FakeItEasy.Creation.CastleDynamicProxy.CastleDynamicProxyGenerator.ProxyInterceptor.Intercept(IInvocation invocation) in C:\projects\fakeiteasy\src\FakeItEasy\Creation\CastleDynamicProxy\CastleDynamicProxyGenerator.cs:line 187
at Castle.DynamicProxy.AbstractInvocation.Proceed()
at Castle.Proxies.DummyAggregateRepositoryProxy.GetById(Guid aggregateId, CancellationToken ct)
at MyCompany.EventStore.Test.AggregateRepositoryTests.GetByIdTests.When_Stream_Exists_Should_Create_Instance_Of_Aggregate_With_Applied_Events() in C:\github\MyCompany_2\libraries\eventstore\test\MyCompany.EventStore.Test\AggregateRepositoryTests\GetByIdTests.cs:line 131
at System.Threading.Tasks.Task.<>c.<ThrowAsync>b__139_0(Object state)
at Xunit.Sdk.AsyncTestSyncContext.<>c__DisplayClass7_0.<Post>b__1(Object _) in C:\Dev\xunit\xunit\src\xunit.execution\Sdk\AsyncTestSyncContext.cs:line 75
Updated after getting new code and stack trace. Original answer left below
I think it's a bug.
Boring explanation:
Strict and Wrapping each add rules to the front of the faked object's rules list. The rules apply to all incoming calls. The first rule found that matches a call is triggered. So in your configuration, Wrapping is added making the Fake attempt to forward all calls to the wrapped object. Then Strict, so now the Fake will reject all calls.
You'd then expect
A.CallTo(() => fakeRepository.GetById(aggregateId, A<CancellationToken>._))
.CallsWrappedMethod();
to add a rule that would cause an incoming matching GetById call to be forwarded to the wrapped method, but the implementation of CallsWrappedMethod
appears to be missing a this.AddRuleIfNeeded() call around line 127. (You can see that CallsBaseMethod just above has this call.)
I've verified that no rule is added by the CallsWrappedMethod configuration. Likely has been broken since implemented in FakeItEasy 6.0.0 (issue #1717).
I created issue #1870 which is now fixed and released as part of FakeItEasy 7.3.1.
Original response, which was wrong, but did ask for more info:
Likely because a call was made to an unconfigured method on a strict faked repository.
We can't see DummyAggregateRepository, so there's going to be some speculation here. Based on the lack of errors earlier, I
assume that GetById is virtual or abstract, so your call should be passed to the wrapped instance.
Nothing jumps out at me as I read your question, but this sort of thing usually pops up when
a call is made to a different fake object than expected, or
a call is made to a different method than expected, usually because there's an overload and the wrong method was configured
a call is made to the expected fake object method, but with unanticipated arguments
If you edit your question, supplying
the FakeItEasy version you're using
the definition of DummyAggregateRepository, and
the entire exception that's returned, including stack traces
we may be able to help better.
I'm trying to mock Http calls for unit test.
To do that I have done the following, I have created a RequestMock case class:
case class RequestMock() {
def sendRequest(httpRequest: HttpRequest)(implicit actorSystem: ActorSystem): Future[HttpResponse] = {
Http().singleRequest(httpRequest)
}
}
and in my service, I have written the following piece of code :
case class Service(requestHandler: RequestMock) {
....
for {
response <- {
requestHandler.sendRequest(
HttpRequest(
method = HttpMethods.GET,
uri = "http://database:9000"
)
)
} yield {
response
}
}
For the unit test, I'm trying to mock HttpCalls, to do that, I have done the following :
def test_2 = mock[RequestMock]
And for defining the mock behaviour I have done the following
when(test_2.sendRequest(
HttpRequest(
method = HttpMethods.GET,
uri = "http://database:9000")
)).thenReturn{
Future(
HttpResponse(
StatusCodes.OK,
entity = HttpEntity(ContentTypes.`text/plain(UTF-8)`,"connection established"))
But, when I execute unit tests, I always get the following error:
java.lang.NullPointerException
Does anyone know how I can solve this issue ?
A couple of problems.
First of all, test_2 should be a val, not a def.
With def like you have it, you get a different instance every time you access it. So, you define the stub on one instance, but then create your Service with a different one, that does not have sendRequest defined, so returns null by default, and that causes your NPE.
The next problem, that you will probably encounter after you fix this one is that you are not defining all of the behavior.
when(test_2.sendRequest(
HttpRequest(
method = HttpMethods.GET,
uri = "http://database:9000")
))
Only creates a stub for a method call with this specific parameter value. So, if your tests try to make a POST for example or hit a different endpoint, you'll get an NPE again.
Even if you only ever use one request, it is better to define the stub for any argument, to avoid weird NPE failures if the code happens to send a different one (you are writing a test, so should not just assume automatically, that the code will always do what you expect - you would not need the test in the first place if that was the case):
when(test2.sendRequest(any)),thenReturn(Future.successful(...))
(Note Future.successful above – that's the correct way to create Future that is immediately satisfied, what you are doing makes it run on a thread ... not a big deal in your case, but still icky).
Then, after the test code is run, you can check that the parameter value passed to the sendRequest was actually what you expect:
verify(test2)
.sendRequest(HttpRequest(method = HttpMethods.GET, uri = "http://database:9000"))
I am writing a unit test for a plugin using Dynamics CRM with RhinoMocks.
After stubbing out the OrganizationService.Retrieve() method, when I invoke the stubbed out method, I am getting null back.
From what I can see (correct me if I'm wrong), is that the stubbed out method signature must the same as the invocation signature.
Here is my code:
TestSetup
var someGuid = Guid.Empty;
var organisationServiceMock = MockRepository.GenerateMock<IOrganizationService>();
organisationServiceMock.Expect(x => x.Retrieve("someCrmEntity", someGuid, SomeCrmEntityColumnSetQuery.ColumnSet))
.Return(new Entity
{
LogicalName = "someCrmEntity",
Id = Guid.NewGuid(),
});
SomeCrmEntityColumnSetQuery Code
public static class SomeCrmEntityColumnSetQuery
{
public static ColumnSet ColumnSet => new ColumnSet("column1", "column2");
}
Invocation Code
var someEntity = organisationServiceMock.Retrieve("someCrmEntity", someGuid, SomeCrmEntityColumnSetQuery.ColumnSet);
//someEntity is null
Things I have tried
Removed the ColumnSet and replaced it with null - this works
Replaced the static class SomeCrmEntityColumnSetQuery with a default instance (new ColumnSet())
I have set the someGuid to Guid.Empty thinking that it was not "joining" on the correct Guid hence the null return value.
I have tried to replace .Expect() with .Stub() - no joy
Edit
In the expectation, I have tried the .WhenCalled(...) and that is how I found out that if I replace the columnSet argument with a null in the expectation and the invocation, it works. So it's go to do with something in my static class that represents a ColumnSet. The code works as I have it running in my DEV environment.
If anyone can share some light on this, that would be magic!
Charles
So I found the answer after watching a PluralSight video on RhinoMocks.
My problem was that when setting up the stub, the stub does not take values but rather the signature of the method that you are stubbing out. For e.g:
var organisationServiceMock = MockRepository.GenerateMock();
//Wrong
organisationServiceMock.Expect(x => x.Retrieve("someCrmEntity", someGuid, SomeCrmEntityColumnSetQuery.ColumnSet)).Return(new Entity());
//The stub does not care about what values are being sent into the method when invoked but rather if the method signature types match.
//Correct
organisationServiceMock.Expect(x => x.Retrieve(Arg.Is.Anything, Arg.Is.Anything, Arg.Is.Anything)).Return(new Entity());
//During the invocation, stubbed method now expects the first argument to be a string, then 2nd to be a Guid, 3rd to be a ColumnSet.
I hope this helps anyone who has also been struggling with this. :)
I'm new rather new to Scala so I think this might be a very small problem.
I'm currently trying to change the method chat from using the deprecated WebSocket.async to WebSocket.tryAccept. The application uses the sample chat found at PlayFramework websocket-chat
I'm having trouble creating the complex Future type that the method requires.
This is the old method:
def chat() = WebSocket.async[JsValue] {
request =>
ChatRoom.join("User: 1")
}
New method:
def chat2() = WebSocket.tryAccept[JsValue] {
request =>
try {
// ChatRoom.join returns (iteratee,enumerator)
ChatRoom.join("User: 1").map(e => Right(e))
} catch {
case e: Exception =>
Left(Ok("Failed")) // Error here
}
}
My error message:
found : Left[Result,Nothing]
required: Future[Either[Result,(Iteratee[JsValue, _], Enumerator[JsValue])]]
I have no idea how I am supposed to create such a complex result for such a simple message.
Although ChatRoom.join("User: 1").map(e => Right(e)) doesn't show any errors now, I'm unsure if this is the correct implementation.
I'm not in front of an IDE at the moment, so I can't answer fully, but the return type it's asking for isn't as complex as it seems. An "Either" is a "Left" or a "Right" in the same way that an "Option" is a "Some" or a "None". So what it's asking for is a Future (which Websocket.async should also have required) that contains either a Left[Result] -- the fail-to-connect case, or a Right[(Iteratee, Enumerator)] -- the success case. Assuming that Chatroom.join returns a Future[(Iteratee, Enumerator)], the map operation is simply wrapping that in a "Right". The first thing I'd try is wrapping Left(Ok("Failed")) in a Future and see what happens.
Mocked setup below (the GenerateTrades() and other methods in ContextFactory are just returning a List AsQueryable with sample data):
_trades = ContextFactory.GenerateTrades();
_hedges = ContextFactory.GenerateHedges();
_exposures = ContextFactory.GenerateExposures();
_ctx = new Mock<FxContext>();
var fakeTrades = new Mock<DbSet<Trade>>();
fakeTrades.As<IQueryable<Trade>>().Setup(m => m.Provider).Returns(_trades.Provider);
fakeTrades.As<IQueryable<Trade>>().Setup(m => m.Expression).Returns(_trades.Expression);
fakeTrades.As<IQueryable<Trade>>().Setup(m => m.ElementType).Returns(_trades.ElementType);
fakeTrades.As<IQueryable<Trade>>().Setup(m => m.GetEnumerator()).Returns(_trades.GetEnumerator());
var fakeHedges = new Mock<DbSet<Hedge>>();
fakeHedges.As<IQueryable<Hedge>>().Setup(m => m.Provider).Returns(_hedges.Provider);
fakeHedges.As<IQueryable<Hedge>>().Setup(m => m.Expression).Returns(_hedges.Expression);
fakeHedges.As<IQueryable<Hedge>>().Setup(m => m.ElementType).Returns(_hedges.ElementType);
fakeHedges.As<IQueryable<Hedge>>().Setup(m => m.GetEnumerator()).Returns(_hedges.GetEnumerator());
var fakeExposures = new Mock<DbSet<Exposure>>();
fakeExposures.As<IQueryable<Exposure>>().Setup(m => m.Provider).Returns(_exposures.Provider);
fakeExposures.As<IQueryable<Exposure>>().Setup(m => m.Expression).Returns(_exposures.Expression);
fakeExposures.As<IQueryable<Exposure>>().Setup(m => m.ElementType).Returns(_exposures.ElementType);
fakeExposures.As<IQueryable<Exposure>>().Setup(m => m.GetEnumerator()).Returns(_exposures.GetEnumerator());
_ctx.Setup(c => c.Trades).Returns(fakeTrades.Object);
_ctx.Setup(c => c.Hedges).Returns(fakeHedges.Object);
_ctx.Setup(c => c.Exposures).Returns(fakeExposures.Object);
Part of test code looks like:
_sut = (from x in _ctx.Object.Hedges
where x.Id == ContextFactory.s_hedge01Id
select x).FirstOrDefault();
_ctx.Object.Hedges.Attach(_sut);
_ctx.Object.Entry(_sut).Collection(x => x.HedgedTrades).Load();
On the last line I get an exception:
{"Member 'Load' cannot be called for property 'HedgedTrades' because the entity of type 'Hedge' does not exist in the context. To add an entity to the context call the Add or Attach method of DbSet<Hedge>."}
I have verified that in fact the _sut Hedge is actually an instance of a Hedge (not null or a stub) and as the code seems to indicate, I have attached the Hedge to the context explicitly (though I would think the query should bring the object into the context automagically). Am I missing something?
It seems like here in your test you are mixing two separate approaches. Error you received states that you are trying to access DbContext inherited logic, but it is mocked. If you want to perform your unit tests against database with use of FxContext then do not mock it. If you want test other part of software then you should mock interface that FxContext should implement. This will enable you to fullfil dependency injection principle in your code which will help you then organize your test in more predictable way.