Avoid Thread Sleep Unit Testing - unit-testing

I have the below method which uses websocket connection to send request,
public void sendLoginRequest(){
WebSocket webSocket = webSocketConnection.getSocketConnection();
Thread.sleep(300 * 1000);
JSONObject loginJson = new JSONObject();
loginJson.put("username","test");
webSocket.sendText(loginJson.toString());
}
I have created my tested case with,
#Test
public void testSendLoginRequest() {
obj.sendLoginRequest();
}
Due to Thread.sleep, it's waiting for 5 min. I'm just curious to control this flow, and make sure the data send to websocket. As far as i know verify method invokes on Mock object, but in this case how can i achieve it.
P.S: I use com.refinitiv.qc.ert.infrastructure.socket.WebSocketConnection API.

Related

Google mock on gRPC

I want to test client and thus mocking server by gmock.
My proto is defined as
// The greeting service definition.
service Greeter {
// Streaming request and reply
rpc StreamRequestAndReply (stream Request) returns (stream Reply) {}
}
message Request {
int32 idx = 1;
bool is_pause = 2; // control message
}
message Reply {
string msg = 1;
bool is_eof = 2;
}
And the correspinding function on server-side looks like
Status StreamRequestAndReply(ServerContext *context, ServerReaderWriter<Reply, Request> *stream) override {
// do something
}
My question is: how to write my predefined Reply message via the mocked stub by gmock, for example I want to reply three valid message and then set is_eof in the fourth one?
My current thinking is using testing::Invoke, but haven't figured out how to capture the stream and call the Write function. Can someone give me some suggestions and hints?
Synchronous gRPC provides virtual functions for all interfaces, which could be mocked by StubInterface.
Asynchronous gRPC (i.e. CompletionQueue) doesn't provide such functionality, since it's just a thin wrapper around C implementation. In this case, better to set-up a local fake server, and unit test it in an integration-like way.

JMS integration testing

I am trying to write an integration test for JMS service which looks like something like this.
#JmsListener(destination = "mailbox", containerFactory = "myFactory")
public void receiveMessage(Email message) throws InterruptedException {
try {
sendEmail(message);
}catch (Exception e){
LOGGER.log(Level.SEVERE,"Failed to deliver email",e);
Thread.sleep(TimeUnit.SECONDS.toSeconds(Optional.of(retryInterval).orElse(5)));
throw e;
}
}
private void sendEmail(Email message){
...............
}
First of all, can I mock this some how? I tried mocking it, but when I send a message the spring boot application is calling the actual JMS bean not the mock one. Seems like this is not possible.
Even if this is not possible, can I at least aoutowire the bean and somehow check if the receiveMessage method is being invoked. Furthermore, if it is being invoked, the sendEmail part should be faked so that it does not do any work. I have a few ideas such as creating a subclass for testing, but not happy with either of them. So wanted to if you can suggest me a better work around?
One approach is to use different profiles for say development, integration test and production and annotate the different components and your integration test class accordingly.
#Component
#Profile("it")
public class MessageReceiverIT {
#JmsListener(destination = "mailbox", containerFactory = "myFactory")
public void receiveMessage(SimpleMessage email) {
log.info("Integration test pretend to receive {}", email);
// (...)
This is the Integration test that uses the same Application class as the real Application, but if a message is received the MessageReceiverIT.receiveMessage() method will be invoked instead of the production component:
#RunWith(SpringRunner.class)
#SpringBootTest(classes=Application.class)
#ActiveProfiles("it")
public class JmsIntegrationTest {
#Inject
ConfigurableApplicationContext context;
#Test
public void testSend() throws Exception{
JmsTemplate jmsTemplate = context.getBean(JmsTemplate.class);
jmsTemplate.convertAndSend("mailbox", new SimpleMessage("it", "we need more IT"));
// (...)
Also check out Spring Boot Testing for alternative approaches such as the use of #TestConfiguration. I'm using Spring Boot in my examples, but there should be similar approaches if you have a none Spring Boot Application.

aem-mocks property test a servlet

Trying to write some proper AEM integration tests using the aem-mocks framework. The goal is to try and test a servlet by calling its path,
E.g. an AEM servlet
#SlingServlet(
paths = {"/bin/utils/emailSignUp"},
methods = {"POST"},
selectors = {"form"}
)
public class EmailSignUpFormServlet extends SlingAllMethodsServlet {
#Reference
SubmissionAgent submissionAgent;
#Reference
XSSFilter xssFilter;
public EmailSignUpFormServlet(){
}
public EmailSignUpFormServlet(SubmissionAgent submissionAgent, XSSFilter xssFilter) {
this.submissionAgent = submissionAgent;
this.xssFilter = xssFilter;
}
#Override
public void doPost(SlingHttpServletRequest request, SlingHttpServletResponse response) throws IOException {
String email = request.getParameter("email");
submissionAgent.saveForm(xssFilter.filter(email));
}
}
Here is the corresponding test to try and do the integration testing. Notice how I've called the servlet's 'doPost' method, instead of 'POST'ing via some API.
public class EmailSignUpFormServletTest {
#Rule
public final AemContext context = new AemContext();
#Mock
SubmissionAgent submissionAgent;
#Mock
XSSFilter xssFilter;
private EmailSignUpFormServlet emailSignUpFormServlet;
#Before
public void setup(){
MockitoAnnotations.initMocks(this);
Map<String,String> report = new HashMap<>();
report.put("statusCode","302");
when(submissionAgent.saveForm(any(String.class)).thenReturn(report);
}
#Test
public void emailSignUpFormDoesNotRequireRecaptchaChallenge() throws IOException {
// Setup test email value
context.request().setQueryString("email=test.only#mail.com");
//===================================================================
/*
* WHAT I END UP DOING:
*/
// instantiate a new class of the servlet
emailSignUpFormServlet = new EmailSignUpFormServlet(submissionAgent, xssFilter);
// call the post method (Simulate the POST call)
emailSignUpFormServlet.doPost(context.request(),context.response());
/*
* WHAT I WOULD LIKE TO DO:
*/
// send request using some API that allows me to do post to the framework
// Example:
// context.request().POST("/bin/utils/emailSignUp") <--- doesn't exist!
//===================================================================
// assert response is internally redirected, hence expected status is a 302
assertEquals(302,context.response().getStatus());
}
}
I've done a lot of research on how this could be done (here) and (here), and these links show a lot about how you can set various parameters for context.request() object. However, they just don't show how to finally execute the 'post' call.
What you are trying to do is mix a UT with IT so this won't be easy at least with the aem-mocks framework. Let me explain why.
Assuming that you are able to call your required code
/*
* WHAT I WOULD LIKE TO DO:
*/
// send request using some API that allows me to do post to the framework
// Example:
// context.request().POST("/bin/utils/emailSignUp") <--- doesn't exist!
//===================================================================
Your test will end up executing all the logic in SlingAllMethodsServlet class and its parent classes. I am assuming that this is not what you want to test as these classes are not part of your logic and they already have other UT/IT (under respective Apache projects) to cater for testing requirements.
Also, looking at your code, bulk of your core logic resides in following snipper
String email = request.getParameter("email");
submissionAgent.saveForm(xssFilter.filter(email));
Your UT criteria is already met by the following line of your code:
emailSignUpFormServlet.doPost(context.request(),context.response());
as it covers most of that logic.
Now, if you are looking for proper IT for posting the parameters and parsing them all the way down to doPost method then aem-mocks is not the framework for that because it does not provide it in a simple way.
You can, in theory, mock all the layers from resource resolver, resource provider and sling servlet executors to pass the parameters all the way to your core logic. This can work but it won't benefit your cause because:
Most of the code is already tested via other UT
Too many internal mocking dependencies might make the tests flaky or version dependant.
If you really want to do pure IT, then it will be easier to host the servlet in an instance and access it via HttpClient. This will ensure that all the layers are hit. A lot of tests are done this way but it feels a bit heavy handed for the functionality you want to test and there are better ways of doing it.
Also the reason why context.request().POST doesn't exist is because context.request() for is a mocked state for the sake of testing. You want to actually bind and mock Http.Post operations which needs some way to resolve to your servlet and that is not supported by the framework.
Hope this helps.

How to unit test Akka.Net Actor State (using Become())

I have an Actor and when it recieves a StartMessage, it should change state using Become(Started). How do I unit test whether or not the Actor's state has changed to Started() ?
MyActor class
public class MyActor : ReceiveActor
{
public MyActor()
{
Receive<StartMessage>(s => {
Become(Started); // This is what I want to unit test
});
}
private void Started()
{
Console.WriteLine("Woo hoo! I'm started!");
}
}
Unit Test
[TestMethod]
public void My_actor_changes_state_to_started()
{
// Arrange
var actor = ActorOfAsTestActorRef<MyActor>(Props.Create(() => new MyActor()));
// Act
actor.Tell(new StartMessage());
// Assert
var actorsCurrentState = actor.UnderlyingActor.STATE; // <-- This doesn't work
Assert.AreEqual(Started, actorsCurrentState);
}
UPDATE
Related to the answer from tomliversidge: My reason for writing this unit test was academic but in reality, it's not a good unit test which is why you aren't able to do it as I'd hoped. From Petabridge's Unit Testing Guide:
In reality, if one actor wants to know the internal state of another actor then it must send that actor a message. I recommend you follow the same pattern in your tests and don’t abuse the TestActorRef. Stick to the messaging model in your tests that you actually use in your application.
You would normal test this by message passing. For example, what messages do you process in the Started state? I'm presuming your example has been simplified to the Console.WriteLine action inside of Started.
If you send the StartMessage and then a second message that is processed when in the Started state you can then assert on a response to this second message.
As a simple suggestion:
private void Started()
{
Receive<StartMessage>(msg => {
Sender.Tell(new AlreadyStarted());
}
}
if StartMessage is received whilst in the Started state, you can then assert on receiving an AlreadyStarted message.
For more info check out the Petabridge article https://petabridge.com/blog/how-to-unit-test-akkadotnet-actors-akka-testkit/

Webservice alive forever

I often use webservice this way
public void CallWebservice()
{
mywebservice web = new mywebservice();
web.call();
}
but sometimes I do this
private mywebservice web;
public Constructor()
{
web = new mywebservice();
}
public void CallWebservice()
{
web.call();
}
The second approach likes me very much but sometimes it times out and I had to start the application again, the first one I think it brings overhead and it is not very efficient, in fact, sometimes the first call returns a WebException - ConnectFailure (I don't know why).
I found an article (Web Service Woes (A light at the end of the tunnel?)) that exceeds the time out turning the KeepAlive property to false in the overriden function GetWebRequest, here's is the code:
Protected Overrides Function GetWebRequest(ByVal uri As System.Uri) As System.Net.WebRequest
Dim webRequest As Net.HttpWebRequest = CType(MyBase.GetWebRequest(uri), Net.HttpWebRequest)
webRequest.KeepAlive = False
Return webRequest
End Function
The question is, is it possible to extend forever the webservice time out and finally, how do you implement your webservices to handle this issue?
The classes generated by Visual Studio for webservices are just proxies with little state so creating them is pretty cheap. I wouldn't worry about memory consumption for them.
If what you are looking for is a way to call the webmethod in one line you can simply do this:
new mywebservice().call()
Cheers