Caching a processed message for the lifetime of a stream - akka

I am redoing a previous question to make it more focused and clear.
I have the following situation:
case class Hello(u:String) extends A
case class Goodbye extends A
case class GoodbyeAck(u:String) extends B
val myProcessor: Flow[A, B, Unit] = Flow[A]
.map {
case Hello(u:String) => // I want to cache u (the username)
case Goodbye => GoodbyeAck(u)
}
So, at the beginning of the stream I get a Hello(username) and at the end of the stream, I receive a Goodbye. I want to reply with Goodbye(username).
How should I cache the username (u) so it will be available for the lifetime of the stream, so I can have it when it's time to say good bye? Is there some context I can leverage? Or do I need to do it outside the framework?

This seems like one of the few examples where mutable state is necessary. Though not "purely functional", the state can be isolated in such a way as to not allow outside influence but still provide the functionality you are looking for.
Note: your question does not specify what B value should be returned by the map in the case of receiving a Hello. A value of type B is necessary since simply caching is of type Unit. Therefore a flatMapConcat is used to conform to the requirements of the Flow in the question, which is to return nothing when a Hello is received:
def cacheProcessor(defaultString : String = "") : Flow[A, B, Unit] = {
var userCache : String = defaultString
Flow[A] flatMapConcat {
case Hello(u : String) => {
userCache = u
Source.empty[B]
}
case Goodbye => Source.single[B](GoodbyeAck(userCache))
}
}//end def cacheProcessor
Although userCache is mutable state it cannot be accessed outside of the returned Flow.flatMapConcat. One important point is that cacheProcessor has to be a def so that there is a unique userCache for each Flow.

Related

Assert mock call with argument assigned in where block in Spock

I have a method that among others generates an identifier, sends it to some external dependency and returns it. I want to have a unit test that tests if the same value that was sent there is returned.
Let's say that the test and the code look like this:
def "test"() {
given:
def testMock = Mock(TestMock)
and:
def x
when:
def testClass = new TestClass()
x = testClass.callMethod(testMock)
then:
1 * testMock.method(x)
}
static interface TestMock {
void method(double x)
}
static class TestClass {
double callMethod(TestMock mock) {
double x = Math.random()
mock.method(x)
return x
}
}
The code works correct, however the test fails with a message:
One or more arguments(s) didn't match:
0: argument == expected
| | |
| | null
| false
0.5757686318956925
So it looks like the mock check in then is done before the value is assigned in when block.
Is there a way to make Spock assign this value before he checks the mock call? Or can I do this check in a different way?
The only idea I have is to inject an id-generator to the method (or actually to the class) and stub it in the test, but it would complicate the code and I would like to avoid it.
I fixed code example according to kriegaex comment.
Fixing the sample code
Before we start, there are two problems with your sample code:
1 * testMock(x) should be 1 * testMock.method(x)
callMethod should return double, not int, because otherwise the result would always be 0 (a double between 0 and 1 would always yield 0 when converted to an integer).
Please, next time make sure that your sample code not only compiles but also does the expected thing. Sample code is only helpful if it does not have extra bugs, which a person trying to help you needs to fix first before being able to focus on the actual problem later on.
The problem at hand
As you already noticed, interactions, even though lexically defined in a then: block, are transformed in such a way by Spock's compiler AST transformations, that they are registered on the mock when the mock is initialised. That is necessary because the mock must be ready before calling any methods in the when: block. Trying to directly use a result only known later while already executing the when: block, will cause the problem you described. What was first, chicken or egg? In this case, you cannot specify a method argument constraint, using the future result of another method calling the mock method in the constraint.
The workaround
A possible workaround is to stub the method and capture the argument in the closure calculating the stub result, e.g. >> { args -> arg = args[0]; return "stubbed" }. Of course, the return keyword is redundant in the last statement of a closure or method in Groovy. In your case, the method is even void, so you do not need to return anything at all in that case.
An example
I adapted your sample code, renaming classes, methods and variables to more clearly describe which is what and what is happening:
package de.scrum_master.stackoverflow.q72029050
import spock.lang.Specification
class InteractionOnCallResultTest extends Specification {
def "dependency method is called with the expected argument"() {
given:
def dependency = Mock(Dependency)
def randomNumber
def dependencyMethodArg
when:
randomNumber = new UnderTest().getRandomNumber(dependency)
then:
1 * dependency.dependencyMethod(_) >> { args -> dependencyMethodArg = args[0] }
dependencyMethodArg == randomNumber
}
}
interface Dependency {
void dependencyMethod(double x)
}
class UnderTest {
double getRandomNumber(Dependency dependency) {
double randomNumber = Math.random()
dependency.dependencyMethod(randomNumber)
return randomNumber
}
}
Try it in the Groovy Web Console.

Mocked ReactiveX streams and Singles doesn't emit elements

I am testing some functionality based on RxJava using Mockito to mock objects. I have a place where I need to mock a value for returning method which is Single<HttpResponse<Buffer>> but when I do this no element is emitted from that Single. I checked values in debugger and it seems to be the same object (the one mocked in the beginning and the other, returned from the method that should emit a value). But it doesn't behave as expected and my stream ends empty.
Here are my mocks and returning rules:
WebClient webClient = mock(WebClient.class);
HttpRequest<Buffer> httpRequest = mock(HttpRequest.class);
HttpResponse<Buffer> httpResponse = mock(HttpResponse.class);
when(httpResponse.statusCode()).thenReturn(200);
when(httpResponse.bodyAsString()).thenReturn(String.format("{\"%s\" : \"%s\"}", "address", testAddress));
when(httpRequest.addQueryParam(any(), any())).thenReturn(httpRequest);
when(httpRequest.rxSend()).thenReturn(Single.just(httpResponse)); // this returned Single doesn't emit the value
when(webClient.post(any())).thenReturn(httpRequest);
Other mocked objects are returned correctly, these are webClient, httpRequest and httpResponse. The Single I am talking about is also returned correctly (it holds a mocked object in value field, I checked that in debugger) but It doesn't emit it.
The emission should happen here:
#Override
public Single<String> registerUserWallet(String userHash) {
Single<HttpResponse<Buffer>> test = httpClient.post(EthereumApiEndpoints.MANAGED_ACCOUNT.uri)
.addQueryParam("path", userHash)
.rxSend();
return test
.doOnSubscribe(() -> log.debug("debug")) // none of this logs are printed out
.doOnEach(x -> log.debug("debug"))
.doOnError(x -> log.debug("debug"))
.doOnSuccess(x -> log.debug("debug"))
.flatMap(this::handleResponse);
}
I created test variable to check its value in debugger. Every objects are in place, httpRequest and httpResponsework well, the problem is with emission ofSingle> test`.
Edit: The method where the Single is used:
private Observable<AbstractMap.SimpleEntry<UserWallet, String>> mapWalletWithAddress(UserWallet wallet) {
return userWalletDao.findFirstRegisteredWalletsForUserInNetwork(wallet.getUserId(),
blockchainIntegration.getNetwork())
.map(UserWallet::getAddress)
.doOnNext(alreadyRegisteredAddress -> log.info("Found already registered address for user " +
"{} in {} network", wallet.getUserId(), blockchainIntegration.getNetwork()))
.onErrorResumeNext(blockchainIntegration.registerUserWallet(wallet.getUserId()).toObservable()
.doOnNext(generatedAddress -> log.info("Generated new address {} for user {}.",
generatedAddress, wallet.getUserId())))
.map(walletAddress -> new AbstractMap.SimpleEntry<>(wallet, walletAddress))
.doOnNext(walletAddressPair -> log.info("Mapped wallet {} with address {}.",
walletAddressPair.getKey(), walletAddressPair.getValue()));
}
}
I am trying to find what is wrong for hours. I hope you guys will find it in a no time.

FakeItEasy - How to verify nested arguments value C#

I need your help in order to find a way of verifying the value of nested objects passed as a parameter of the method under test invocation.
Assume this class:
public class AuditTrailValueObject
{
public ActionType Action { get; private set; }
public EntityType EntityType { get; private set; }
public long EntityId { get; private set; }
public DateTime StartTime { get; private set; }
public bool IsSuccess { get; private set; }
public string Remarks { get; private set; }
public AuditTrailValueObject(ActionType action, EntityType entityType, long entityId, DateTime startTime, bool isSuccess, string remarks = "")
{
Action = action;
EntityType = entityType;
EntityId = entityId;
StartTime = startTime;
IsSuccess = isSuccess;
Remarks = remarks;
}
}
And the following interface has this class as an injected dependency:
public interface IAuditTrailService
{
void WriteToAuditTrail(AuditTrailValueObject auditParamData);
}
Now I have the ScanService depending on the AuditTrailService (which implements IAuditTrailService):
public long CreateScanRequest(long projectId)
{
ScanRequestWriteModel scanRequest = _scanRequestWriteModelFactory.Create(projectDetails);
long scanRequestId = _scanRequestsWriteRepository.Insert(scanRequest);
_auditTrailService.WriteToAuditTrail(new AuditTrailValueObject(ActionType.Run, EntityType.SastScanRequest, scanRequestId, DateTime.UtcNow, true));
return scanRequestId;
}
The test I've written:
[TestMethod]
public void Scan_GivenProjectId_ShouldAuditSuccess()
{
//Given
var projectId = 100;
var scanService = CreateScanService();
...
A.CallTo(() => _scanRequestWriteModelFactory.Create(projectDetails)).Returns(new ScanRequestWriteModel());
A.CallTo(() => _scanRequestsWriteRepository.Insert(A<ScanRequestWriteModel>._)).Returns(1);
//When
var scanRequestId = scanService.CreateScanRequest(projectId);
//Then
A.CallTo(() => _auditTrailService.WriteToAuditTrail(
new AuditTrailValueObject(ActionType.Run, EntityType.SastScanRequest, scanRequestId, A<DateTime>._, true, A<string>._))).MustHaveHappened();
}
When running this test I'm getting:
System.InvalidCastException: Specified cast is not valid
How can I verify the value of a nested parameter in AuditTrailValueObject?
#tom redfern makes many good points, which you may want to address. But after rereading your code and comments, I think I an immediate way forward. Your code has at least one problem, and it may have another.
Let's look at
A.CallTo(() => _auditTrailService.WriteToAuditTrail(
new AuditTrailValueObject(ActionType.Run,
EntityType.SastScanRequest,
scanRequestId,
A<DateTime>._,
true
A<string>._)))
.MustHaveHappened();
The _ constructs are being used here inside the AuditTrailValueObject constructor, and they are not valid there. They'll result in default values being assigned to the AuditTrailValueObject, (DateTime.MinValue and null, I think), and are almost not what you want. if you extract the new out to the previous line, you'll see FakeItEasy throw an error when _ is used. I think that it should do a better job of helping you find the problem in your code, but I'm not sure it's possible. I've created FakeItEasy Issue 1177 -
Argument constraint That, when nested deeper in A.CallTo, misreports what's being matched to help FakeItEasy improve.
Related to this is how FakeItEasy matches objects. When provided with a value to compare, (the result of new AuditTrailValueObject(…)) FakeItEasy will use Equals to compare the object against the received parameter. Unless your AuditTrailValueObject has a good Equals, this will fail.
If you want to keep using AuditTrailValueObject and don't want to provide an Equals (that would ignore the startTime and the remarks), there are ways forward.
First, you could use That.Matches, like so:
A.CallTo(() => _auditTrailService.WriteToAuditTrail(A<AuditTrailValueObject>.That.Matches(
a => a.Action == ActionType.Run &&
a.EntityType == EntityType.SastScanRequest &&
a.EntityId == scanRequestId &&
a.IsSuccess)))
.MustHaveHappened();
Some people aren't wild about complex constraints in the Matches, so an alternative is to capture the AuditTrailValueObject and interrogate it later, as Alex James Brown has described in his answer to Why can't I capture a FakeItEasy expectation in a variable?.
Your problem is a symptom of a larger problem: you are trying to do too much with one test.
Because you're newing-up an instance of AuditTrailValueObject in your WriteToAuditTrail() method, you will have no means of accessing this object instance as it is created within the method scope and is therefore immune to inspection.
However, it appears that the only reason you wish to access this object in the first place is so that you can verify that the values being set within it are correct.
Of these values, only one (as far as your code sample allows us to know) is set from within the calling method. This is the return value from the call made to _scanRequestsWriteRepository.Insert(), which should be the subject of its own unit test where you can verify correct behaviour independently of where it is being used.
Writing this unit test (on the _scanRequestsWriteRepository.Insert() method) will actually address the underlying cause of your problem (that you are doing too much with a single test). Your immediate problem, however, still needs to be addressed. The simplest way of doing this is to remove the AuditTrailValueObject class entirely, and just pass your arguments directly to the call to WriteToAuditTrail().
If I'll remove AuditTrailValueObject where the place should I verify
what params are being passed to the auditTrailService? What I mean is
that also if I've tested the auditTrailService I need to know that
scan service call if with the right parameters (for example: with
ActionType.Run and not with ActionType.Update).
To verify that the correct parameters have been passed to the call to WriteToAuditTrail() you can inject a fake of IAuditTrailService and verify your call has happened:
A.CallTo(
() => _auditTrailService.WriteToAuditTrail(
ActionType.Run,
EntityType.SastScanRequest,
scanRequestId,
myDateTime,
true,
myString)
).MustHaveHappened();

What is the optimal way (not using Scalaz) to type require a non-empty List?

As I am working a design model, I am torn between two different methods of indicating a parameter of type List must be nonEmpty. I began by using List[Int] with an accompanying require statement to verify the List is nonEmpty.
case class A(name: String, favoriteNumbers: List[Int]) {
require(favoriteNumbers.nonEmpty, "favoriteNumbers must not be empty")
}
I then needed to make the list optional. If the List is provided, it must be nonEmpty. I'm using using Option[List[Int]] with an accompanying require statement to verify, if the Option is nonEmpty, the list must also be nonEmpty.
case class B(name: String, favoriteNumbers: Option[List[Int]]) {
require(
favoriteNumbers.isEmpty || favoriateNumbers.get.nonEmpty
, "when defined, favoriteNumbers.get must be nonEmpty"
)
}
However, I need to use this non-empty List all over the system I am modeling. This means that my code has these same require statements duplicated everywhere. Is there a (non-ScalaZ) way to have a new type, say NeList, which is defined and behaves identically to List, with the only change being an exception is thrown when NeList attempts to be instantiated with no elements?
I tried to Google for this and couldn't find a set of search terms to hone on this area. I either got really simple List how-tos, or all sorts of references to ScalaZ's NEL (Non Empty List). So, if there is a link out there that would help with this, I would love to see it.
If you
def foo[A](x: ::[A]) = "List has length "+x.length
then you insist that the list be nonempty. But of course your lists are all typed as List, so you need a helper method to give you a nonempty list:
implicit class NonEmptyList[A](private val underlying: List[A]) {
def ifNonEmpty[B](f: ::[A] => B): Option[B] = {
underlying match {
case x: ::[A #unchecked] => Some(f(x))
case _ => None
}
}
}
Now you can safely apply the operation to get an Option out. (You could also run side-effecting functions in a foreach-like method.)
Now, this is rather non-idiomatic Scala. But it is safe at compile time (the #unchecked notwithstanding--Scala's compiler isn't quite smart enough to realize that the type parameter hasn't changed).
You could implement a non-empty list yourself with implicit conversions between List[A] and Nel[A]:
case class Nel[A](val head: A, val tail: List[A] = Nil)
implicit def list2Nel[A](list: List[A]): Nel[A] = {
require(!list.isEmpty)
Nel(list.head, list.tail)
}
implicit def nel2List[A](nel: Nel[A]): List[A] = nel.head :: nel.tail
Then you can define your functions where this is needed such that they take a Nel[A] as a parameter:
def f(l: Option[Nel[String]]) = { ... }
And call them with normal lists (assuming the implicit defs are in scope):
f(Some(List("hello", "world")) // works
f(Some(Nil)) // throws IllegalArgumentException
f(None) // works
EDIT: It should be noted that this does not provide compile time guarantees that the List[A] passed in will not be empty. If that's what you want, then get rid of the implicit def list2Nel and require clients of your function to pass in an Nel[A] explicitly, thus guaranteeing at compile time that the list is not empty.
Also, this is a very basic NonEmptyList implementation. A more complete solution is found in scalaz (granted it was specifically requested in the question that scalaz not be used): https://github.com/scalaz/scalaz/blob/series/7.2.x/core/src/main/scala/scalaz/NonEmptyList.scala

Covariance and Scala Collections

I'm trying to get my head around the covariance of Scala's collections. I have the following:
abstract class MediaFormat{
def name:String
def status:String
}
case class H264_high(status:String="on") extends MediaFormat {
def name = "h264_high"
}
case class H264_med(status:String="on") extends MediaFormat {
def name = "h264_med"
}
case class H264_low(status:String="on") extends MediaFormat {
def name = "h264_low"
}
case class H264_syndication(status:String="off") extends MediaFormat {
def name = "h264_syndication"
}
What I wanted to do was have a set of all of these formats because I need a collection where each format only occurs once, so I tried:
object MediaFormat {
val allFormats:Set[MediaFormat] = Set(H264_high,H264_low)
}
This gave me a compile time exception because, as I now understand, Set is invariant.
So I think, well I guess I'll just have to use a List and manage the repeated values myself
but then I try this:
object MediaFormat {
val allFormats:List[MediaFormat] = List(H264_high,H264_low)
}
because as I understand it, List is covariant, but that still doesn't compile.
Can someone help me understand what I should do to get a collection of my formats?
It doesn't compile because you are referencing the companion object (module), not the case classes! The compile error (which you should have posted) is nothing to do with variance. It will work, with Set if you do this:
val allFormats: Set[MediaFormat] = Set(H264_high(), H264_low())
^^ ^^
Or alternatively;
val allFormats = Set[MediaFormat](H264_high(), H264_low())
However, it makes no sense for these to be case classes given your description of the problem; I would just make them modules, i.e.
case object H264_syndication extends MediaFormat {
def status = "off"
def name = "h264_syndication"
}
Then your original code will work just fine. Or I would make them vals as follows:
case class MediaFormat(status: String, name: String)
val H264_syndication = MediaFormat(status ="off", name = "h264_syndication")
I think this would be my preference; I rarely use abstract classes any more to be honest (normally, I am dishonest).
Explanation: Covariance means the following:
G[S] <: G[T] iff S <: T
The fact that Set is invariant, means that a Set[S] is not a subtype of Set[T] (for S <: T), but it does not mean that such a Set[T] may not contain elements of type S.