0

나는 최근에 unittest.monkey.patch과 그 변종에 대해 배웠고 파일 읽기 기능의 원 자성에 대한 단위 테스트에 사용하고 싶습니다. 그러나이 패치는 아무런 효과가없는 것 같습니다.unittest로 io.RawIOBase.read 메소드를 패치하는 방법은 무엇입니까?

여기가 제 설정입니다. 조사에서이 방법이 너무 (abriged) 같은 약이다 :

#local_storage.py 

def read(uri): 
    with open(path, "rb") as file_handle: 
     result = file_handle.read() 
    return result 

그리고 단위 (도 abriged) 시험을 수행하는 모듈 :

#test/test_local_storage.py 

import unittest.mock 
import local_storage 

def _read_while_writing(io_handle, size=-1): 
    """ The patch function, to replace io.RawIOBase.read. """ 

    _write_something_to(TestLocalStorage._unsafe_target_file) #Appends "12". 
    result = io_handle.read(size) #Should call the actual read. 
    _write_something_to(TestLocalStorage._unsafe_target_file) #Appends "34". 

class TestLocalStorage(unittest.TestCase): 
    _unsafe_target_file = "test.txt" 

    def test_read_atomicity(self): 
     with open(self._unsafe_target_file, "wb") as unsafe_file_handle: 
      unsafe_file_handle.write(b"Test") 

     with unittest.mock.patch("io.RawIOBase.read", _read_while_writing): # <--- This doesn't work! 
      result = local_storage.read(TestLocalStorage._unsafe_target_file) #The actual test. 
      self.assertIn(result, [b"Test", b"Test1234"], "Read is not atomic.") 

이 방법을, 패치가 확인해야합니다 때마다 그것을 읽으려고하면, 파일은 실제 읽기 직전과 직후에 수정됩니다. 마치 동시에 발생하는 것처럼, 우리의 읽기의 원 자성을 테스트합니다.

단위 테스트는 현재 성공했지만 print 함수를 사용하여 패치 함수가 실제로 호출되지 않았 음을 확인 했으므로 파일에 추가로 쓰기 ("테스트"라고 함)가 표시되지 않습니다. 또한 코드를 목적에 맞게 비 원자력으로 수정했습니다.

내 질문 : read IO 핸들의 기능을 local_storage 모듈에 어떻게 패치 할 수 있습니까? 다른 사람들이 open() 함수를 대체하여 StringIO과 같은 것을 반환하는 경향이 있지만이 문제를 해결할 수있는 방법을 모르겠습니다.

파이썬 3.4 이상을 지원해야합니다.

+0

당신이'open'을 조롱하는 방법을 볼 수 봤어 : 당신은 여기 내 솔루션을 볼 수 있습니다

? [this] (http://www.voidspace.org.uk/python/mock/helpers.html#mock-open)을 읽으십시오. 그러나 때로는'StringIO'가 파일 시스템에 직접 쓰지 않는 것으로 보았습니다. – idjaw

+0

파이썬 3에서는 지원됩니다. [here] (https://docs.python.org/3/library/unittest.mock.html#mock-open) – idjaw

+0

조금 전에 해결책을 썼습니다. 컨텍스트 관리자. 그 주변의 세부 사항은 당신이하려는 일과 정확히 관련이 없지만, 컨텍스트 관리자의 본성을 설명하고 공개적으로 사용합니다. 희망은 도움이 : http : // stackoverflow.com/a/33652204/1832539 – idjaw

답변

0

드디어 해결책을 찾았습니다.

문제는 mock은 C로 작성된 개체의 방법을 조롱 할 수 없다는 것입니다.이 중 하나는 내가 만난 RawIOBase입니다.

정말 해결책은 open을 모방하여 RawIOBase 주위에 래퍼를 반환하는 것이 었습니다. 나는 나를 위해 래퍼를 만들기 위해 mock을 얻을 수 없었다. 그래서 나는 그것을 직접 구현했다.

'안전하지 않은 것으로 간주되는 하나의 미리 정의 된 파일이 있습니다. 랩퍼는 랩퍼에 대한 호출이있을 때마다이 "안전하지 않은"파일에 기록합니다. 이것은 쓰는 동안 안전하지 않은 파일에 추가 사항을 기록하므로 파일 쓰기의 원 자성을 테스트 할 수 있습니다. 필자의 구현은 임시 ("안전한") 파일에 쓰고 그 파일을 대상 파일로 옮김으로써 이것을 막는다.

랩퍼에는 read 기능에 대한 특별한 경우가 있습니다. 정확하게 원자를 테스트하기 위해 중에 읽는 동안 파일에 쓸 필요가 있습니다. 따라서 파일의 처음 절반을 읽은 다음 정지하고 뭔가를 쓰고 읽습니다. 이 솔루션은 현재 반쯤 하드 코드되어 있지만 (중간 정도까지),이를 개선 할 수있는 방법을 찾을 것입니다. https://github.com/Ghostkeeper/Luna/blob/0e88841d19737fb1f4606917f86e3de9b5b9f29b/plugins/storage/localstorage/test/test_local_storage.py

관련 문제