Skip to content

Commit

Permalink
Improve code reuse in mapper unit tests
Browse files Browse the repository at this point in the history
  • Loading branch information
olim7t committed Jun 21, 2019
1 parent a19b668 commit 4562576
Show file tree
Hide file tree
Showing 12 changed files with 113 additions and 111 deletions.
Expand Up @@ -15,6 +15,8 @@
*/
package com.datastax.oss.driver.internal.mapper.processor;

import static com.google.testing.compile.CompilationSubject.assertThat;

import com.google.testing.compile.Compilation;
import com.google.testing.compile.Compiler;
import com.squareup.javapoet.JavaFile;
Expand All @@ -39,4 +41,21 @@ protected Compilation compileWithMapperProcessor(String packageName, TypeSpec...
}
return Compiler.javac().withProcessors(new MapperProcessor()).compile(files);
}

protected void should_fail_with_expected_error(
String expectedError, String packageName, TypeSpec... typeSpecs) {
Compilation compilation = compileWithMapperProcessor(packageName, typeSpecs);
assertThat(compilation).hadErrorContaining(expectedError);
}

protected void should_succeed_with_expected_warning(
String expectedWarning, String packageName, TypeSpec... typeSpecs) {
Compilation compilation = compileWithMapperProcessor(packageName, typeSpecs);
assertThat(compilation).hadWarningContaining(expectedWarning);
}

protected void should_succeed_without_warnings(String packageName, TypeSpec... typeSpecs) {
Compilation compilation = compileWithMapperProcessor(packageName, typeSpecs);
assertThat(compilation).succeededWithoutWarnings();
}
}
Expand Up @@ -13,11 +13,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.datastax.oss.driver.internal.mapper.processor;
package com.datastax.oss.driver.internal.mapper.processor.dao;

import static com.google.testing.compile.CompilationSubject.assertThat;

import com.datastax.oss.driver.api.mapper.annotations.Dao;
import com.datastax.oss.driver.internal.mapper.processor.MapperProcessorTest;
import com.google.testing.compile.Compilation;
import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.TypeSpec;
Expand Down Expand Up @@ -50,14 +51,12 @@ public void should_work_on_nested_interface() {

@Test
public void should_fail_on_class() {
Compilation compilation =
compileWithMapperProcessor(
"test",
TypeSpec.classBuilder(ClassName.get("test", "Foo"))
.addModifiers(Modifier.PUBLIC)
.addAnnotation(Dao.class)
.build());

assertThat(compilation).hadErrorContaining("Only INTERFACE elements can be annotated with Dao");
should_fail_with_expected_error(
"Only INTERFACE elements can be annotated with Dao",
"test",
TypeSpec.classBuilder(ClassName.get("test", "Foo"))
.addModifiers(Modifier.PUBLIC)
.addAnnotation(Dao.class)
.build());
}
}
Expand Up @@ -39,65 +39,66 @@ public class DaoGetEntityMethodGeneratorTest extends DaoMethodGeneratorTest {
@Test
@Override
@UseDataProvider("invalidSignatures")
public void should_fail_with_expected_error(MethodSpec method, String expectedError) {
super.should_fail_with_expected_error(method, expectedError);
public void should_fail_with_expected_error(String expectedError, MethodSpec method) {
super.should_fail_with_expected_error(expectedError, method);
}

@DataProvider
public static Object[][] invalidSignatures() {
return new Object[][] {
{
"Wrong number of parameters: GetEntity methods must have exactly one",
MethodSpec.methodBuilder("get")
.addAnnotation(GetEntity.class)
.addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
.build(),
"Wrong number of parameters: GetEntity methods must have exactly one"
},
{
"Wrong number of parameters: GetEntity methods must have exactly one",
MethodSpec.methodBuilder("get")
.addAnnotation(GetEntity.class)
.addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
.addParameter(ParameterSpec.builder(String.class, "a").build())
.addParameter(ParameterSpec.builder(String.class, "b").build())
.build(),
"Wrong number of parameters: GetEntity methods must have exactly one"
},
{
"Invalid parameter type: GetEntity methods must take a GettableByName, ResultSet or AsyncResultSet",
MethodSpec.methodBuilder("get")
.addAnnotation(GetEntity.class)
.addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
.addParameter(ParameterSpec.builder(String.class, "a").build())
.build(),
"Invalid parameter type: GetEntity methods must take a GettableByName, ResultSet or AsyncResultSet"
},
{
"Invalid return type: GetEntity methods must return a Entity-annotated class, or a PagingIterable or MappedAsyncPagingIterable thereof",
MethodSpec.methodBuilder("get")
.addAnnotation(GetEntity.class)
.addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
.addParameter(ParameterSpec.builder(Row.class, "source").build())
.build(),
"Invalid return type: GetEntity methods must return a Entity-annotated class, or a PagingIterable or MappedAsyncPagingIterable thereof"
},
{
"Invalid return type: GetEntity methods must return a Entity-annotated class, or a PagingIterable or MappedAsyncPagingIterable thereof",
MethodSpec.methodBuilder("get")
.addAnnotation(GetEntity.class)
.addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
.addParameter(ParameterSpec.builder(ResultSet.class, "source").build())
.returns(ParameterizedTypeName.get(PagingIterable.class, Integer.class))
.build(),
"Invalid return type: GetEntity methods must return a Entity-annotated class, or a PagingIterable or MappedAsyncPagingIterable thereof"
},
{
"Invalid return type: GetEntity methods must return PagingIterable if the argument is ResultSet",
MethodSpec.methodBuilder("get")
.addAnnotation(GetEntity.class)
.addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
.addParameter(ParameterSpec.builder(Row.class, "source").build())
.returns(
ParameterizedTypeName.get(ClassName.get(PagingIterable.class), ENTITY_CLASS_NAME))
.build(),
"Invalid return type: GetEntity methods must return PagingIterable if the argument is ResultSet"
},
{
"Invalid return type: GetEntity methods must return MappedAsyncPagingIterable if the argument is AsyncResultSet",
MethodSpec.methodBuilder("get")
.addAnnotation(GetEntity.class)
.addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
Expand All @@ -106,7 +107,6 @@ public static Object[][] invalidSignatures() {
ParameterizedTypeName.get(
ClassName.get(MappedAsyncPagingIterable.class), ENTITY_CLASS_NAME))
.build(),
"Invalid return type: GetEntity methods must return MappedAsyncPagingIterable if the argument is AsyncResultSet"
},
};
}
Expand Down
Expand Up @@ -26,12 +26,12 @@ public class DaoImplementationGeneratorTest extends DaoMethodGeneratorTest {
@Test
public void should_fail_if_method_is_not_annotated() {
should_fail_with_expected_error(
"Unrecognized method signature: no implementation will be generated",
MethodSpec.methodBuilder("get")
.addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
.addParameter(ParameterSpec.builder(Row.class, "source").build())
.returns(ENTITY_CLASS_NAME)
.build(),
"Unrecognized method signature: no implementation will be generated");
.build());
}

@Test
Expand Down
Expand Up @@ -36,37 +36,37 @@ public class DaoInsertMethodGeneratorTest extends DaoMethodGeneratorTest {
@Test
@Override
@UseDataProvider("invalidSignatures")
public void should_fail_with_expected_error(MethodSpec method, String expectedError) {
super.should_fail_with_expected_error(method, expectedError);
public void should_fail_with_expected_error(String expectedError, MethodSpec method) {
super.should_fail_with_expected_error(expectedError, method);
}

@DataProvider
public static Object[][] invalidSignatures() {
return new Object[][] {
{
"Wrong number of parameters: Insert methods must have at least one",
MethodSpec.methodBuilder("insert")
.addAnnotation(Insert.class)
.addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
.build(),
"Wrong number of parameters: Insert methods must have at least one"
},
{
"Invalid parameter type: Insert methods must take the entity to insert as the first parameter",
MethodSpec.methodBuilder("insert")
.addAnnotation(Insert.class)
.addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
.addParameter(ParameterSpec.builder(String.class, "a").build())
.build(),
"Invalid parameter type: Insert methods must take the entity to insert as the first parameter"
},
{
"Invalid return type: Insert methods must return either void or the entity class "
+ "(possibly wrapped in a CompletionStage/CompletableFuture)",
MethodSpec.methodBuilder("insert")
.addAnnotation(Insert.class)
.addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
.addParameter(ParameterSpec.builder(ENTITY_CLASS_NAME, "entity").build())
.returns(TypeName.INT)
.build(),
"Invalid return type: Insert methods must return either void or the entity class "
+ "(possibly wrapped in a CompletionStage/CompletableFuture)"
},
};
}
Expand Down
Expand Up @@ -15,12 +15,9 @@
*/
package com.datastax.oss.driver.internal.mapper.processor.dao;

import static com.google.testing.compile.CompilationSubject.assertThat;

import com.datastax.oss.driver.api.mapper.annotations.Dao;
import com.datastax.oss.driver.api.mapper.annotations.Entity;
import com.datastax.oss.driver.internal.mapper.processor.MapperProcessorTest;
import com.google.testing.compile.Compilation;
import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.MethodSpec;
import com.squareup.javapoet.TypeName;
Expand Down Expand Up @@ -49,42 +46,38 @@ public abstract class DaoMethodGeneratorTest extends MapperProcessorTest {
.build())
.build();

protected void should_fail_with_expected_error(MethodSpec method, String expectedError) {
TypeSpec daoSpec =
protected void should_fail_with_expected_error(String expectedError, MethodSpec method) {
should_fail_with_expected_error(
expectedError,
"test",
ENTITY_SPEC,
TypeSpec.interfaceBuilder(ClassName.get("test", "ProductDao"))
.addModifiers(Modifier.PUBLIC)
.addAnnotation(Dao.class)
.addMethod(method)
.build();

Compilation compilation = compileWithMapperProcessor("test", ENTITY_SPEC, daoSpec);

assertThat(compilation).hadErrorContaining(expectedError);
.build());
}

protected void should_succeed_with_expected_warning(MethodSpec method, String expectedWarning) {
TypeSpec daoSpec =
protected void should_succeed_with_expected_warning(String expectedWarning, MethodSpec method) {
should_succeed_with_expected_warning(
expectedWarning,
"test",
ENTITY_SPEC,
TypeSpec.interfaceBuilder(ClassName.get("test", "ProductDao"))
.addModifiers(Modifier.PUBLIC)
.addAnnotation(Dao.class)
.addMethod(method)
.build();

Compilation compilation = compileWithMapperProcessor("test", ENTITY_SPEC, daoSpec);

assertThat(compilation).hadWarningContaining(expectedWarning);
.build());
}

protected void should_succeed_without_warnings(MethodSpec method) {
TypeSpec daoSpec =
should_succeed_without_warnings(
"test",
ENTITY_SPEC,
TypeSpec.interfaceBuilder(ClassName.get("test", "ProductDao"))
.addModifiers(Modifier.PUBLIC)
.addAnnotation(Dao.class)
.addMethod(method)
.build();

Compilation compilation = compileWithMapperProcessor("test", ENTITY_SPEC, daoSpec);

assertThat(compilation).succeededWithoutWarnings();
.build());
}
}
Expand Up @@ -34,87 +34,87 @@ public class DaoSetEntityMethodGeneratorTest extends DaoMethodGeneratorTest {
@Test
@Override
@UseDataProvider("invalidSignatures")
public void should_fail_with_expected_error(MethodSpec method, String expectedError) {
super.should_fail_with_expected_error(method, expectedError);
public void should_fail_with_expected_error(String expectedError, MethodSpec method) {
super.should_fail_with_expected_error(expectedError, method);
}

@DataProvider
public static Object[][] invalidSignatures() {
return new Object[][] {
{
"Wrong number of parameters: SetEntity methods must have two",
MethodSpec.methodBuilder("set")
.addAnnotation(SetEntity.class)
.addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
.addParameter(ParameterSpec.builder(String.class, "a").build())
.build(),
"Wrong number of parameters: SetEntity methods must have two"
},
{
"Wrong number of parameters: SetEntity methods must have two",
MethodSpec.methodBuilder("set")
.addAnnotation(SetEntity.class)
.addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
.addParameter(ParameterSpec.builder(String.class, "a").build())
.addParameter(ParameterSpec.builder(String.class, "b").build())
.addParameter(ParameterSpec.builder(String.class, "c").build())
.build(),
"Wrong number of parameters: SetEntity methods must have two"
},
{
"Wrong parameter types: SetEntity methods must take a SettableByName and an annotated entity (in any order)",
MethodSpec.methodBuilder("set")
.addAnnotation(SetEntity.class)
.addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
.addParameter(ParameterSpec.builder(ENTITY_CLASS_NAME, "entity").build())
.addParameter(ParameterSpec.builder(Integer.class, "target").build())
.build(),
"Wrong parameter types: SetEntity methods must take a SettableByName and an annotated entity (in any order)"
},
{
"Wrong parameter types: SetEntity methods must take a SettableByName and an annotated entity (in any order)",
MethodSpec.methodBuilder("set")
.addAnnotation(SetEntity.class)
.addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
.addParameter(ParameterSpec.builder(String.class, "entity").build())
.addParameter(ParameterSpec.builder(BoundStatement.class, "target").build())
.build(),
"Wrong parameter types: SetEntity methods must take a SettableByName and an annotated entity (in any order)"
},
{
"Invalid return type: SetEntity methods must either be void, or return the same type as their settable parameter "
+ "(in this case, com.datastax.oss.driver.api.core.cql.BoundStatement to match 'target')",
MethodSpec.methodBuilder("set")
.addAnnotation(SetEntity.class)
.addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
.addParameter(ParameterSpec.builder(ENTITY_CLASS_NAME, "entity").build())
.addParameter(ParameterSpec.builder(BoundStatement.class, "target").build())
.returns(Integer.class)
.build(),
"Invalid return type: SetEntity methods must either be void, or return the same type as their settable parameter "
+ "(in this case, com.datastax.oss.driver.api.core.cql.BoundStatement to match 'target')"
},
// Return type is a SettableByName, but not the same subtype as the parameter:
{
"Invalid return type: SetEntity methods must either be void, or return the same type as their settable parameter "
+ "(in this case, com.datastax.oss.driver.api.core.cql.BoundStatement to match 'target')",
MethodSpec.methodBuilder("set")
.addAnnotation(SetEntity.class)
.addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
.addParameter(ParameterSpec.builder(ENTITY_CLASS_NAME, "entity").build())
.addParameter(ParameterSpec.builder(BoundStatement.class, "target").build())
.returns(UdtValue.class)
.build(),
"Invalid return type: SetEntity methods must either be void, or return the same type as their settable parameter "
+ "(in this case, com.datastax.oss.driver.api.core.cql.BoundStatement to match 'target')"
},
};
}

@Test
public void should_warn_when_void_and_target_is_bound_statement() {
super.should_succeed_with_expected_warning(
"BoundStatement is immutable, "
+ "this method will not modify 'target' in place. "
+ "It should probably return BoundStatement rather than void",
MethodSpec.methodBuilder("set")
.addAnnotation(SetEntity.class)
.addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
.addParameter(ParameterSpec.builder(ENTITY_CLASS_NAME, "entity").build())
.addParameter(ParameterSpec.builder(BoundStatement.class, "target").build())
.build(),
"BoundStatement is immutable, "
+ "this method will not modify 'target' in place. "
+ "It should probably return BoundStatement rather than void");
.build());
}

@Test
Expand Down

0 comments on commit 4562576

Please sign in to comment.