mardi 3 octobre 2017

Test method fails when @Transactional

I am writing my end-to-end tests for an application. One of those tests will verify that when some required input is missing, it will not persist the data to the database. All is running fine, untill I decided to annotate my test class with @Transactional, since I don't need to persist the results when the tests are finished. The moment I add the @Transactionalannotation, the application is suddenly ok with a non-null field to be null.

How the database is set up:

create table MY_TABLE
(
    MY_FIELD VARCHAR(20) NOT NULL
)

The corresponding model:

@Entity
@Table(name = "MY_TABLE")
public class MyObject {

    @Column(name = "MY_FIELD", nullable = false)
    private String MyField = null;
}

Saving goes via the service layer:

@Service
public class MyAppServiceImpl implements MyAppService {

    @Inject
    private MyObjectRepository myObjectRepository;  //this interface extends CrudRepository<MyObject , Long>

    @Override
    @Transactional
    public MyObject save(MyObject myObject) {
        return myObjectRepository.save(myObject);
    }
}

In the resource layer, the value of myField is set to NULL, so at the moment the data is persisted, I should receive an ORA-error

@Controller
public class MyAppResourceImpl implements MyAppResource {

    @Inject
    private MyAppService myAppService;

    public ResponseEntity doPost(@RequestBody String xml) {
        MyObject myobject = new MyObject();
        myObject.setMyField(null);
        try {
            myAppService.save(myObject);
            return new ResponseEntity(null, HttpStatus.CREATED);
        } catch (SomeExceptions e) {
            return new ResponseEntity("Could not save", HttpStatus.BAD_REQUEST);
        }
    }
}

Finally, the test:

@RunWith(SpringRunner.class)
@SpringBootTest
//@Transactional
public class MyAppResourceImplEndToEndTest {
    @Inject
    private MyAppResourceImpl myAppResource;

    @Test
    public void testWithFieldNull() throws Exception {
         ResponseEntity response = myAppResource.doPost("some-xml");
         Assertions.assertThat(response.GetStatusCode()).isEqualTo(HttpStatus.BAD_REQUEST);
    }
}

This test works, as expected, but other tests persist data into the database. This is not the behavior I wanted, so I annotated the test class with @Transactional. Now no tests persist their results to the database, but this specific test method fails because

Expected :400
Actual   :201

Why does the @Transactional annotation suddenly cause NULL values to be persisted in NOT NULL columns?

Aucun commentaire:

Enregistrer un commentaire