Testing antlr4 visitor rules - unit-testing

I've got a fairly complicated antlr4 grammar that utilizes a visitor pattern. I'd like to test parts of the visitor. What's a good way to test individual visit rules?
My visitor has tons of rules like this that I want to test:
#Override
public Object visitQux(ExclParser.QuxContext ctx) {
return visitChildren(ctx);
}
And my test code basically is the following:
PrintStream ps = new PrintStream(stdError, false /* autoFlush */, "UTF-8")
ANTLRInputStream input = new ANTLRInputStream(is);
MyLexer lexer = new MyLexer(input);
CommonTokenStream tokens = new CommonTokenStream(lexer);
MyParser parser = new MyParser(tokens);
parser.removeErrorListeners();
MyErrorListener errorListener = new MyErrorListener(ps, filename);
parser.addErrorListener(errorListener);
MyVisitor visitor = new MyVisitor();
visitor.setParser(filename, parser, errorListener);
ParseTree tree = parser.qux(); // <--- This is the line I want to vary.
Object result = visitor.visit(tree);
assertThat(describeExpectation(), result, equalTo(this.expectedOutput));
Ideally I would be able to test any visitor using a parameterized test. But to get the parse tree I want to visit (parser.qux) I can't specify any variant of qux() in a table because parser.qux() is not static.
Any thoughts?

I created an example project on how ANTLR-visitors could be tested (using Mockito&TestNG). The full source code can be found on GitHub. Here are the most important parts:
public class MyVisitor extends DemoBaseVisitor<String> {
#Override
public String visitPlus(final DemoParser.PlusContext ctx) {
return visit(ctx.left) + " PLUS " + visit(ctx.right);
}
#Override
public String visitLiteralNumber(final DemoParser.LiteralNumberContext ctx) {
return ctx.getText();
}
}
Any my test for that visitor:
public class MyVisitorTest {
private final MyVisitor myVisitor = new MyVisitor();
#Test
public void visitPlus_joinsOperatorsWithWordPLUSAsSeparator() throws Exception {
// setup
final DemoParser.PlusContext plusNode = mock(DemoParser.PlusContext.class);
plusNode.left = mockForVisitorResult(DemoParser.ExpressionContext.class, "2");
plusNode.right = mockForVisitorResult(DemoParser.ExpressionContext.class, "4");
// execution
final String actual = myVisitor.visitPlus(plusNode);
// evaluation
assertEquals(actual, "2 PLUS 4");
}
private<T extends RuleContext> T mockForVisitorResult(final Class<T> nodeType, final String visitResult) {
final T mock = mock(nodeType);
when(mock.accept(myVisitor)).thenReturn(visitResult);
return mock;
}
#Test
public void visitLiteralNumber_returnsTextValueOfNumber() throws Exception {
// setup
final DemoParser.LiteralNumberContext literalNumberNode = mock(DemoParser.LiteralNumberContext.class);
when(literalNumberNode.getText()).thenReturn("42");
// execution
final String actual = myVisitor.visitLiteralNumber(literalNumberNode);
// evaluation
assertEquals(actual, "42");
}
}
In your special example where you have a method which calls visitChildren() your would test that calling that method returns the aggregated result of visiting all child nodes (what the aggregation is depends on your implementation of the aggregateResult method).

Reflection may be the right answer here:
Method method = MyParser.class.getDeclaredMethod("qux");
ParseTree tree = (ParseTree) method.invoke(parser);
is a suitable replacement for:
ParseTree tree = parser.qux();

Related

Unit testing of SimpleChannelInboundHandler<FullHTTPRequest> in netty

I am new to netty framework.We have a API Handler implementing SimpleChannelInboundHandler and overriding the ChannelRead0 function that takes ChannelHandlerContext and the FullHTTPRequest.Now I need to do unit testing mocking the inputs.
Can anyone help me with this.
Lets assume I want to test my MyContentExtractionHandler, which looks like this:
public class MyContentExtractionHandler extends SimpleChannelInboundHandler<FullHttpRequest> {
#Override
protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest msg) throws Exception {
int contentLenght = msg.content().capacity();
byte[] content = new byte[contentLenght];
msg.content().getBytes(0, content);
ctx.fireChannelRead(new String(content));
}
}
I will create a regular DefaultFullHttpRequest and use mockito to mock a ChannelHandlerContext. My unit test would look like this:
public class MyContentExtractionHandlerTest {
#Mock
ChannelHandlerContext mockCtx = BDDMockito.mock(ChannelHandlerContext.class);
MyContentExtractionHandler myContentExtractorHandler = new MyContentExtractionHandler();
#Test
public void myTest() throws Exception {
String content = "MyContentHello";
DefaultFullHttpRequest fullHttpRequest = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.POST, "/my /uri", Unpooled.copiedBuffer(content.getBytes()));
myContentExtractorHandler.channelRead(mockCtx, fullHttpRequest);
BDDMockito.verify(mockCtx).fireChannelRead(content); //verify that fireChannelRead was called once with the expected result
}
}
Most possibly, your SimpleChannelInboundHandler will be the final handler. So instead of checking for fireChannelRead() check for whatever method you call after reading the message.

How to verify some other object was constructed, when using mockito

I have following Java code that I want to test. What I am having difficulty is figuring out how do I verify that call to handleAppVersionRequest , actually constructs AppVersionResponse object. Is there any way to do that using Mockito?
Here code is code for method:
class MyClass {
public void handleAppVersionRequest(String dataStr,
final int dataChannelId) {
String ver = "1.0";
final AppVersionResponse resp = new AppVersionResponse(ver);
Timber.d("Sending data %s", resp.toString());
sendResponse(dataChannelId, getGson().toJson(resp));
}
}
And here is method for test:
#Test
public void testHandleAppVersionRequest() throws Exception {
MyClass presenter = Mockito.spy(new MyClass());
String versionRequestJson = "{\"command\":1}";
when(presenter.getGson()).thenReturn(gSon);
presenter.handleAppVersionRequest(versionRequestJson,0);
// How do I verify that AppResponse object was constructed?
verify(presenter,times(1)).sendResponse(anyInt(),anyString());
}
If you must test the creation of the object during a unit test, you can extract a factory, mock it for your test, and then verify that the create method is called on it.
At the same time, consider spending some time looking at some tutorials for Mockito and unit testing in general, like this one. You should choose one class that is going to be the 'system under test'. Don't spy or mock this class! Instead, pass in mocks as dependencies that you will use to test the behaviour of your class.
Here is a factory extracted from your MyClass:
class AppVersionResponseFactory {
AppVersionResponse create(String version) {
return new AppVersionResponse(version);
}
}
Then the refactored version of your class where the dependencies (Gson and the factory) are passed in through the constructor:
class MyClass {
//dependencies that can now be mocked!
private final AppVersionResponseFactory appVersionResponseFactory;
private final Gson gson;
//pass the mockable dependencies in the constructor of the system under test!
public MyClass(AppVersionResponseFactory appVersionResponseFactory, Gson gson) {
this.appVersionResposeFactory = factory;
this.gson = gson;
}
public void handleAppVersionRequest(String dataStr, final int dataChannelId) {
String ver = "1.0";
AppVersionResponse resp = AppVersionResponseFactory.create(ver);
Timber.d("Sending data %s", resp.toString());
sendResponse(dataChannelId, gson.toJson(resp));
}
}
Now your test looks something like this:
//mocks
AppVersionResponseFactory mockAppVersionResposeFactory;
Gson mockGson;
//system under test
MyClass myClass;
#Before
public void setUp() {
mockAppVersionResposeFactory = Mockito.mock(AppVersionResponseFactory.class);
mockGson = Mockito.mock(Gson.class);
myClass = new MyClass(mockGson, mockAppVersionResposeFactory);
}
#Test
public void testHandleAppVersionRequest() throws Exception {
String versionRequestJson = "{\"command\":1}";
myClass.handleAppVersionRequest(versionRequestJson, 0);
verify(appVersionResposeFactory).create("1.0");
}
Please note that although your question asks for a way to verify the construction of an object, a better test would probably test the final outcome of that method i.e., that sendResponse was called with the correct dataChannelId and correct JSON. You can use the same techniques in this answer to do that i.e., extracting a dependency (perhaps a ResponseSender?), passing it in the constructor for your MyClass, mocking it in the test, then calling verify on it.

Why is AutoFixture Customization causing inherited properties to not be filled?

I wrote the following customization and have it applied as part of a composite on most of my tests. My entities have a read-only Id, but I'm using their SetId method in this customization to make sure all entities have some Id if they are transient (don't have an Id already).
public class SetEntityIdCustomization : ICustomization {
public void Customize(IFixture fixture) {
var engine = ((Fixture)fixture).Engine;
fixture.Customizations.Add(new Postprocessor(
engine, o => {
var entity = o as BaseEntity;
if (entity == null || !entity.IsTransient()) {
return;
}
entity.SetId(fixture.CreateAnonymous<Guid>());
}));
}
}
This has been working great, until I discovered a very odd thing today. If I feed a test one of my entities that directly inherits from BaseEntity, all is well and it's writeable properties are auto-filled. However, if I ask for an entity that inherits from something further down from BaseEntity, my customization prevents the properties from auto-filling.
The User entity in this test method is filled properly:
public class User : BaseEntity {
public string Email { get; set; }
public int CoolThings { get; set; }
}
...
[Theory, AutoDomainData]
public void SomeTest(User user, ...) {
// user.Email and user.CoolThings have auto-filled values, as expected.
...
}
However, the AwesomeUser entity in the following test does not get any of the same properties auto-filled.
public class AwesomeUser : User {
...
}
...
[Theory, AutoDomainData]
public void SomeOtherTest(AwesomeUser user, ...) {
// user.Email nor user.CoolThings have auto-filled values. What gives?
...
}
In both test cases, the Id property is auto-filled because of my customization. If I remove my customization, the SomeOtherTest's AwesomeUser instance gets its inherited properties auto-filled just fine. I must assume that my customization is what is messing things up.
Is there a better way to get all my BaseEntity instances to set their Id, or is there something else I'm missing with AutoFixture? I've applied my customization first, in the middle, and last, to no avail.
The solution provided above is a pretty clever attempt, but not something I've seen before. A more idiomatic solution would be something like this:
public void Customize(IFixture fixture)
{
fixture.Customizations.Add(
new FilteringSpecimenBuilder(
new Postprocessor(
new BaseEntityBuilder(
new ConstructorInvoker(
new ModestConstructorQuery())),
new AutoPropertiesCommand().Execute),
new BaseEntitySpecification()));
}
private class BaseEntityBuilder : ISpecimenBuilder
{
private readonly ISpecimenBuilder builder;
private readonly IRequestSpecification specification;
public BaseEntityBuilder(ISpecimenBuilder builder)
{
this.builder = builder;
this.specification = new BaseEntitySpecification();
}
public object Create(object request, ISpecimenContext context)
{
if (!this.specification.IsSatisfiedBy(request))
return new NoSpecimen(request);
var b = (BaseEntity)this.builder.Create(request, context);
b.SetId((Guid)context.Resolve(typeof(Guid)));
return b;
}
}
private class BaseEntitySpecification : IRequestSpecification
{
public bool IsSatisfiedBy(object request)
{
var t = request as Type;
if (t == null)
return false;
if (!typeof(BaseEntity).IsAssignableFrom(t))
return false;
return true;
}
}
As you can see, this isn't a simple one-liner, which is indicative of AutoFixture being a rather opinionated library. In this case, AutoFixture's opinion is:
Favor object composition over class inheritance.
-Design Patterns, p. 20
AutoFixture is first and foremost a TDD tool, and one of the main advantages of TDD is that it provides feedback about class design. In this case, the feedback is: Inheritance is awkward and troublesome. Reconsider the design.

LINQ Expressions Body ToString

I'm wondering if somebody can explain to me the downside of retrieving
(Expression<Func<T, bool>>) Expression.Body
at runtime and operating on this as a string?
for example given the following
public partial class Tests : Form
{
public Tests()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
TestClass t = new TestClass();
textBox1.Text = t.Evaluate(templates => templates.usable == true && templates.name == "tc1");
}
}
public class TestClass
{
public string name { get; set; }
public bool usable { get; set; }
}
public static class Helpers
{
public static string Evaluate<T>(this T input,Expression<Func<T, bool>> Expression) where T : class
{
return Expression.Parameters.Single().Name + " " + Expression.Body;
}
}
which returns
templates ((templates.usable == True) AndAlso (templates.name == "tc1"))
I'm wondering what sort of performance issues may arise from retrieving this and then parsing it through a Regex expression
in answer to the question why? I've been playing around with Dapper a bit, but none of the pre existing extensions (that I've seen) appeal to me
I would like to be able to operate on it in a similar fashion to EF for example
_repo.Select(templates=>templates.usable== true && templates.id == templateId);
Thanks for the nudge towards using the actual expression rather than parsing the text.
for anybody that's interested I've posted a link to the first draft of my sqlexpression project.Google Code - SqlExpression.cs
The parameters that are created are DynamicParameters from Dapper but could easily be swapped for a standard sql parameter
haven't done alot of testing yet but query appears to perform reasonably well at this stage

Moq - how to verify method call which parameter has been cleaned (a list)

I've got the following code and I need help to write a unit test for it. I'm using Moq library.
Here's the deal. I have a business class with a dependency to a repository (interface), so I can use it to save my entities to the database. My entity is basically a list of strings. The method AddAndSave, from MyBusinessClass, grab the value it receives as a parameters, put it into the list and call Save method from IRepository. Then, I clear the list of my entity. The code below show this example (I've made it simple so I can explain it here).
There's a unit test, too.
using System.Collections.Generic;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
namespace TestesGerais
{
public class MyEntity
{
public MyEntity()
{
MyList = new List<string>();
}
public List<string> MyList { get; set; }
}
public interface IRepository
{
void Save(MyEntity entity);
}
public class MyBusinessClass
{
public IRepository Repository { get; set; }
private MyEntity _entity = new MyEntity();
public void AddAndSave(string info)
{
_entity.MyList.Add(info);
Repository.Save(_entity);
_entity.MyList.Clear(); // for some reason I need to clear it
}
}
[TestClass]
public class UnitTest10
{
[TestMethod]
public void TestMethod1()
{
var mock = new Mock<IRepository>();
MyBusinessClass b = new MyBusinessClass() { Repository = mock.Object };
b.AddAndSave("xpto");
mock.Verify(m => m.Save(It.Is<MyEntity>(x => x.MyList[0] == "xpto")), Times.Exactly(1));
}
}
}
My unit-test check if the IRepository's Save method was called with its parameter (an entity) having one element in the list, and having the value "xpto" in this element.
When I run this test, it turns red with the error message "Test method TestesGerais.UnitTest10.TestMethod1 threw exception:
System.ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the collection.
Parameter name: index".
Ok, this is caused by the list that has been cleaned. If I comment the line "_entity.MyList.Clear();", everything goes well.
My question is: how can I test this without commenting the "Clear" line in my business class, and making sure that my repository's method is called passing the specific value (entity with one element with value "xpto")?
Thanks
I've changed my unit test using the Callback feature of Moq. This way, I can setup the mock so when AddAndSave is called, the parameter it receives is saved into a variable from my unit test, and I can assert it later.
[TestMethod]
public void TestMethod1()
{
var mock = new Mock<IRepository>();
string result = string.Empty;
mock.Setup(m => m.Save(It.IsAny<MyEntity>())).Callback((MyEntity e) => { result = e.MyList[0]; });
MyBusinessClass b = new MyBusinessClass() { Repository = mock.Object };
b.AddAndSave("xpto");
Assert.AreEqual(result, "xpto");
}
You could split your method up a bit. "AddAndSave" isn't all it does. You could then just test the behaviour of the adding and saving bit in isolation.