I am using JustMock and NServiceBus.
I want to assert that following statement is executed once:
_bus.Publish<ISpecialEvent>(x =>
{
x.Prop1= "Very special";
});
so that's what I am using:
void Publish<T>(Action<T> messageConstructor);
Now I am mocking NServiceBus:
var serviceBus = Mock.Create<IBus>();
and assert:
Mock.Assert(() => serviceBus.Publish(Arg.IsAny<ISpecialEvent>()), Occurs.Once());
Well obviously this won't work as this does match the actual usage of .Publish
How do I do that?
it can be done like this:
Publish(Arg.IsAny>())
Related
I will start mentioning I am very new to Scala but I have now to maintain a legacy code where some new feature are being tried to be include.
I have the following code:
Where a list is coming as a parameter where a new output needs to be processed. However it seems like code is not waiting for the response to the external service when processing.
def historyBet(jackpotListUser : List[JackpotBetHistory])(implicit MC: AppMarkerContext) : List[LegacyJackpotHistoryResponse] =
for {
bet <- jackpotListUser
prize = jackpotIntegratorService.findJackpotByJackpotHumanId(bet.jackpotHumanId) match {
case Some(jackpot : JackpotResponse) =>
...
extra code extracting price from jackpot : JackpotResponse
...
extra code generating result with prize
} yield result
How can I do a call to jackpotIntegratorService.findJackpotByJackpotHumanId to execute at that time. instead of returning something that F[Option....?
def findJackpotByJackpotHumanId(
jackpotHumanId: JackpotHumanId
)(implicit MC: AppMarkerContext): F[Option[JackpotResponse]] =
jackpotIntegratorRepo.findJackpotByJackpotHumanId(jackpotHumanId)
where it is finally implemented as:
override def findJackpotByJackpotHumanId(
jackpotHumanId: JackpotHumanId
)(implicit mc: AppMarkerContext): IO[Option[JackpotResponse]] =
... code calling an API which return the IO.
Thanks!
I thought I could do IO.await somewhere... but not sure where or how...
because in the "historyBet" function I got a F[] when it was an IO... so what is the syntax to be able to wait for the response and the continue?
Extra Comment:
The real issue we notice is that the method call is starting (the logs shows part of it) but the caller with in the maps continues too.
prize = jackpotIntegratorService.findJackpotByJackpotHumanId
this part of the code continues even when prize, which we want the final object JackpotResponse, not the IO or F.
So, if your method needs to call an IO then it must return an IO unless you unsafeRunSync them... but, as the name suggest, you should not do that.
So the return type is now: IO[List[LegacyJackpotHistoryResponse]
And can be implemented like this:
def historyBet(jackpotListUser: List[JackpotBetHistory])(implicit MC: AppMarkerContext): IO[List[LegacyJackpotHistoryResponse]] =
jackpotListUser.traverse { bet =>
jackpotIntegratorService.findJackpotByJackpotHumanId(bet.jackpotHumanId).map {
case Some(jackpot) =>
// ...
case None =>
// ...
}
}
I have following setup
A.CallTo(() => fakeChargeService
.CreateAsync(A<ChargeCreateOptions>._, A<RequestOptions>._, A<CancellationToken>._))
.Throws<StripeException>((se) => stripeException);
and then I assert
var msg = await Assert.ThrowsAsync<StripeException>(async () => await mediator.Send(command, CancellationToken.None));
which eventually executes this piece of code
var policyResult = await Policy.Handle<StripeException>(x => x.ShouldRetry())
.WaitAndRetryAsync(new[]
{
TimeSpan.FromSeconds(0.5),
TimeSpan.FromSeconds(1),
TimeSpan.FromSeconds(2),
})
.ExecuteAndCaptureAsync(async () => await this.chargeService.CreateAsync(options, null, cancellationToken));
and here I get error
Assert.Throws() Failure
Expected: typeof(Stripe.StripeException)
Actual: typeof(FakeItEasy.Configuration.FakeConfigurationException): The faked method has the signature (Stripe.ChargeCreateOptions, Stripe.RequestOptions, System.Threading.CancellationToken), but throws was used with (Stripe.StripeException).
I am not sure what is it that I am doing wrong. Any help would be appreciated
You seem to be specifying the wrong signature in your Throws. CreateAsync takes (Stripe.ChargeCreateOptions, Stripe.RequestOptions, System.Threading.CancellationToken), but Throws was used with (Stripe.StripeException).
See the second example in Throwing Exceptions:
// Pass up to 4 original call argument values into the method that creates the exception.
A.CallTo(() => fakeShop.NumberOfSweetsSoldOn(A<DateTime>._))
.Throws((DateTime when)=>new InvalidDateException(when + " is in the future"));
Note that the signature of the lambda and the called method match.
You should update your lambda to match the proper signature. Or better yet, just replace with
.Throws<StripeException>(stripeException)
since there doesn't appear to be any reason to lazily throw, based on the snippet of code you provided.
I'm using ngrx/effects with marbles testing. I have a service that uses promises. I want my effect to call the service and handle both successful and error states. I have code like this
Effect:
.mergeMap(() =>
this.service.getThings()
.map((things) => new SetThingsAction(things))
.catch((error) =>
of(new HandleAPIErrorAction(error))
)
)
.catch((error) =>
of(new HandleAPIErrorAction(error))
);
Service:
public geThings() {
return Observable.fromPromise(this.promiseBasedThing.getTheThings());
}
Then a test:
actions = hot("a", { a: new GetThingsAction() });
const response = cold("-#", {});
service.getThings.and.returnValue( response );
const expected = cold("-b", { b: new HandleAPIErrorAction("error") });
expect(effects.getThings$).toBeObservable(expected);
This actually all works. However the double catch in the effect seems clearly bad and probably suggests I don't understand how Observables work. In the real world only the later catch is effective. In a test the first is effective.
Based on this it seems like Promises don't work with marbles tests. This SO question gives an idea on error handling but it seems impossible to test because it has a Promise.
How can I use ngrx/effects with error handling, promises, and testing.
Can answer my own after further research.
https://jsfiddle.net/btroncone/upy6nr6n/
Basically I needed to do the catch in the getThings instead of in the effect.
getThings() {
return Observable.fromPromise(this.promiseBasedThing.getTheThings())
.catch((error) => Observable.of(error));
}
Also learned that it's much easier to solve these problems with a simple rsjx example instead of trying to solve it while using ngrx/effects too. This still has two catch statements, but the test mocking now matches how it works in reality.
Coming from a Java background, I have been trying to teach myself Scala for some time now. As part of that, I am doing a small pet project that exposes a HTTP endpoint that saves the registration numberof a vehicle against the owner and returns the status.
To give more context, I am using Slick as FRM which performs DB operations asynchronously and returns a Future.
Based on the output of this Future, I want to set the status variable to return back to the client.
Here, is the code
def addVehicleOwner(vehicle: Vehicle): String = {
var status = ""
val addFuture = db.run((vehicles returning vehicles.map(_.id)) += vehicle)
addFuture onComplete {
case Success(id) => {
BotLogger.info(LOGTAG, s"Vehicle registered at $id ")
status = String.format("Registration number - '%s' mapped to owner '%s' successfully", vehicle.registration,
vehicle.owner)
println(s"status inside success $status") //--------- (1)
}
case Failure(e: SQLException) if e.getMessage.contains("SQLITE_CONSTRAINT") => {
status = updateVehicleOwner(vehicle)
BotLogger.info(LOGTAG, s"Updated owner='${vehicle.owner}' for '${vehicle.registration}'")
}
case Failure(e) => {
BotLogger.error(LOGTAG, e)
status = "Sorry, unable to add now!"
}
}
exec(addFuture)
println(s"Status=$status") //--------- (2)
status
}
// Helper method for running a query in this example file:
def exec[T](sqlFuture: Future[T]):T = Await.result(sqlFuture, 1 seconds)
This was fairly simple in Java. With Scala, I am facing the following problems:
The expected value gets printed at (1), but (2) always prints empty string and same is what method returns. Can someone explain why?
I even tried marking the var status as #volatile var status, it still evaluates to empty string.
I know, that the above is not the functional way of doing things as I am muting state. What is the clean way of writing code for such cases.
Almost all the examples I could find described how to map the result of Success or handle Failure by doing a println. I want to do more than that.
What are some good references of small projects that I can refer to? Specially, that follow TDD.
Instead of relying on status to complete inside the closure, you can recover over the Future[T] which handle the exception if they occur, and always returns the result you want. This is taking advantage of the nature of expressions in Scala:
val addFuture =
db.run((vehicles returning vehicles.map(_.id)) += vehicle)
.recover {
case e: SQLException if e.getMessage.contains("SQLITE_CONSTRAINT") => {
val status = updateVehicleOwner(vehicle)
BotLogger.info(
LOGTAG,
s"Updated owner='${vehicle.owner}' for '${vehicle.registration}'"
)
status
}
case e => {
BotLogger.error(LOGTAG, e)
val status = "Sorry, unable to add now!"
status
}
}
val result: String = exec(addFuture)
println(s"Status = $result")
result
Note that Await.result should not be used in any production environment as it synchronously blocks on the Future, which is exactly the opposite of what you actually want. If you're already using a Future to delegate work, you want it to complete asynchronously. I'm assuming your exec method was simply for testing purposes.
Reading Play-Slick DBAction code, I thought that this code might contain a race condition:
object DBAction{
// snip
def apply(r: (RequestWithDbSession) => Result)(implicit app:Application) = {
Action { implicit request =>
AsyncResult {
DB.withSession{ s:scala.slick.session.Session =>
Future(r( RequestWithDbSession(request,s) ))(executionContext)
}
}
}
}
The function r runs at a future time, after withSession has returned a Future[Result], and called session.close(). Is there a race condition in this code?
I am not sure if that is called a race condition. However to me it seems that you are correct that something is wrong here. The session might no longer be valid when the future executes the code.
It would be better to invert the execution and request a database session from within the future:
Async {
Future {
DB.withSession{ s:scala.slick.session.Session =>
r( RequestWithDbSession(request, s) )
}
}
}
I think your are right and fix suggested by EECOLOR looks correct. We are tracking this in a ticket: https://github.com/freekh/play-slick/issues/81
Thx